KnockoutJS: update / insert data in viewModel using mapping

I have been trying to figure this out for quite some time. I could not find anything that could solve this problem, but please correct me if I am wrong.

Problem: I have data from the JSON API that is included with the nested array / object structure. I use matching to initially populate the model with my data. To update this, I want to expand the model if new data appears, or update existing data.

As I understand it, the matching option key should do this trick for me, but I may have misunderstood the functionality of the matching options.

I reviewed the problem that will be presented in this example:

var userMapping = { key: function(item) { return ko.utils.unwrapObservable(item.id); } }; // JSON call replaced with values var viewModel = { users: ko.mapping.fromJS([], userMapping) }; // Should insert new - new ID? ko.mapping.fromJS([{"id":1,"name":"Foo"}, {"id":2,"name":"Bar"}], userMapping, viewModel.users); // Should only update ID#1 - same ID? ko.mapping.fromJS([{"id":1,"name":"Bat"}], userMapping, viewModel.users); // Should insert new - New ID? ko.mapping.fromJS([{"id":3,"name":"New"}, {"id":4,"name":"New"}], userMapping, viewModel.users); ko.applyBindings(viewModel);​ 

Fiddle: http://jsfiddle.net/mikaelbr/gDjA7/

As you can see, the first row inserts data. All is well. But when I try to update, it replaces the contents. The same for the third display; It replaces the content, not extends it.

Am I using this incorrectly? Should I try to expand the contents manually before using the mapping?

Change decision:
I solved this case by having a second helper array storing all current models. According to new data, I expanded this array and updated the view model to contain the accumulated elements.

During the upgrade (in my case the WebSocket message), I went in cycles on the models, changed the contents of the element in question and used the value of the HasMutated () method to notify the changed value in the Knockout library.

+6
source share
3 answers

From looking at your sample code, the display plugin behaves as I expected. When you call fromJS in a collection, you effectively tell the mapping plugin this is the new contents of this collection. For instance:

In the second line, how do you know if you updated or just deleted id: 2?

I cannot find mention of a suitable method that treats the data as just an update, although you can add it. Massive arrays come with some useful methods such as mappedIndexOf to help you find specific elements. If you get an update dataset, just skip it, find the item, and update it by calling mapping.fromJS for that specific item. This can be easily generalized to the reusable method.

+4
source

You can use ko.mapping.updateFromJS() to update existing values. However, it does not add new values, so this will be a problem in your instance. Take a look at the link below for more details.

Using updateFromJS replaces values ​​when they should add them

+1
source

Yes, you must first collect all the data in a list or array, and then apply the mapping to this list. Otherwise, you will overwrite the values ​​in your ViewModel.

0
source

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


All Articles