3
votes

I need to clone some data from a master source in the ViewModel into a dialog. The reason being is that the user could cancel the dialog, and I don't want the master to reflect those cancelled changes.

I create a cloned copy of the master data into the dialog, and the data-bindings are set to pick up 'localEdited.*' properites. If the user clicks ok, I then try and persist the data back to the master if its edited, otherwise push the data if its new data.

   editItem: function(data) { 
            // clone a temporary copy for the dialog                    
            this.localEdited = ko.mapping.fromJS(ko.toJS(data));               
            $("#dlgAdd").dialog("open");
        },

The above currently works, however if I click another item in the master, the dialog isn't showing the updated values. Its as if the ko.mapping.fromJS only works once and then never again. It always picks up the first values. How do I get around this problem? I feel like I need to re-bind the values, but the whole point of KO is to not have to do this.

How do I also persist the data back to the parent. I guess I might have the same problem as above.

BTW, I'm using KnockoutJS 1.2.1.

1

1 Answers

4
votes

localEdited needs to be an observable and you should do this.localEdited(ko.mapping.fromJS(ko.toJS(data))) in editItem function to make knockout rebind your dialog every time editItem is called. Data bindings in the dialog will need to be changed to localEdited().*

You can get away without localEdited being observable, but in this case you will need to manually update each observable property of localEdited in editItem function. So you would have to have something like

this.localEdited.property1(data.property1());
this.localEdited.property2(data.property2());

The point is you need to update observables using function call syntax. This way knockout will catch the update and propagate it through the bindings. In you initial code you just do simple assignment to localEdited, so knockout doesn't have a hook to intercept and do its magic.

UPDATE: It turns out ko.mapping plugin can update individual observables in your model automatically, so you don't have to do it manually:

ko.mapping.fromJS(ko.toJS(data), this.localEdited);