Unable to update knockout user interface with new data object

I am having problems updating the user interface when I get new data from the server for one element that is in an observable array of wrapper objects that contains an object of several observables.

Consider the following:

var vm = { .... localEdited: ko.mapping.fromJS(new ItemWrapper(defaultModelSerialised)), selected: ko.observable(null), editItem: function(data) { // clone a temporary copy of data for the dialog when opening (*.localEdited on dialog) var clonedData = ko.toJS(data); ko.mapping.fromJS(clonedData, null, this.localEdited); // selected should now point to the item in the obserable array which will be refreshed this.selected(data); // open dialog... }, submitDialog: function(data) { // submit data to server... // (1) commit the data back to UI (new item is return in resp.entity from server) vm.selected(new ItemWrapper(resp.entity)); // at this point the UI isn't showing the updated value // (2) however if I do this it reflects the data change in the UI this.selected().Name("changed"); // updates the UI. } 

Can someone explain why passing to ItemWrapper in vm.selected does not update the user interface, whereas in (2) it works. I do not want to configure each property, as in (2) for each property.

ItemWrapper looks like this:

 function PoolWrapper(pool) { this.Name = ko.observable(pool.Name); // more properties... } 
+6
source share
2 answers

OK - the problem is that your clones end up displaying metadata on them, and ultimately this causes recursion when you try to call ko.mapping.fromJS .

The solution is to create your clones using ko.mapping.toJS instead of ko.toJS so that you get a clean clone (without display metadata).

Here is the updated fiddle: http://jsfiddle.net/rniemeyer/tDDBp/

+6
source

Something that I came across today that I decided to share with him:

If you clone using:

 var clone = ko.mapping.fromJS(ko.mapping.toJS(itemToClone)); 

Then the clone will be deprived of any calculated observables. They will exist as the last value of the function, but will no longer function as calculated observables.

If your object is a complex model with calculated observable data that you would like to keep in your clone, you can do the following:

 var clone = ko.mapping.fromJS(ko.mapping.toJS(itemToClone), null, new itemModel()); 

Where itemModel is your complex model for your item containing your calculated observable data.

0
source

Source: https://habr.com/ru/post/908134/


All Articles