Knockout-Contrib / Knockout-Validation

A validation library for Knockout JS
1.02k stars 379 forks source link

Editing series of objects using same form elements #85

Closed sgreer closed 12 years ago

sgreer commented 12 years ago

Hi,

Love the work that you've done on the validation library! However, either I'm doing something wrong, or I'm running into a limitation. Here's my scenario:

I have a form that is used to collect information about one or more persons. Name, email, address information, etc. My view model contains an observable array of Person records and I bind the controls like this:

data-bind="value: currentPerson().FirstName"

self.currentPersonID = new ko.observable(0);

self.currentPerson = function () { return self.People()[self.currentPersonID()]; }

When I push a new Person record into the observable array and set the currentPersonID to the new key, navigation and Knockout bindings work fine. What does not work any longer is validation. I suppose I should create a Fiddle for this, and I will if you need a repro, however I was curious if you knew of any reason why this would not work.

Thanks!

Sean

sgreer commented 12 years ago

I was able to make my situation work by calling ko.cleanNode and then ko.applyBindings after I updated the currentPerson value. I'm not sure that this is a good idea, but I going to move on for now.

ericmbarnard commented 12 years ago

@sgreer

You don't want to call cleanNode and re-apply the bindings unless you are doing very low-level framework type of code. It's expensive and could yield very confusing problems for you in the future.

Here's what I usually do when I'm working on some kind of master-details scenario:

// constructor function
var ViewModel = function(){
     var self = this;

     this.selectedPerson = ko.observable(); // holds the entire selected person object
     this.persons = ko.observableArray([]); // my person collection

     this.newPerson_Click = function(){
          self.selectedPerson(new Person());
     }

     // ... etc
};

Both KO and KO.Validation are very reliant upon closures, and so I can see where the code you currently have might be creating some kind of closure state in the binding that isn't responding to updates.

sgreer commented 12 years ago

Eric,

I have switched my approach to use a single observable that wraps my Person object and the navigation is working fine. I did not realize that I could wrap a complex object in that manner, complete with UI updates - very cool.

However, I am continuing to have an issue with validation and have created a Fiddle that illustrates the problem:

http://jsfiddle.net/sgreer/x9JAz/6/

I have followed your approach, having a selectedPerson observable and a list of Person objects. For the first person, validation works great - both first and last name are required. After adding a new Person object, the validation for that object does not fire. I will next move this to a test page and do some spelunking in the debugger, however if you have any insights, that would be great.

ericmbarnard commented 12 years ago

@sgreer

This is an example of how I tend to setup my master-details type views: http://jsfiddle.net/x9JAz/9/

One thing I noticed is that if you use "selectedPerson().firstName" in your data-bind statement - both ko and ko.validation will create closures around the current binding (which is your first 'Person' object) ... if selectedPerson changes, the bindings are still tracking the first person that they bound to.

I use the with binding to conquer that problem, but there are other strategies as well.