Pregunta

I am using knockout mapping plugin to map JSON data to knockout view model. The issue is JSON comes from server data doesn't have all the properties always. But my computed obeservables refer them. So I creates all the observable in first mapping using an empty object(templateStructure) contains all properties and then doing seocond call with actual data to populate the observable with current data. This works fine but want to know that if there any better way to handle the situation?

This is how the two time call is happening right now. templateStructure is dummay object with all the properties and data is actual data.

ko.mapping.fromJS(templateStructure, {}, this);
ko.mapping.fromJS(data, {}, this);
¿Fue útil?

Solución 2

I have solved it using jQuery extend method by merging the object before mapping. So I only needed one call to the mapping function.

         var mergedData = jQuery.extend(true,data,templateStructure);
         ko.mapping.fromJS(mergedData, {}, this);

Otros consejos

Calling mapping.fromJS to update an existing view model is right. If you're receiving updates to your model using AJAX, it's the easiest way to do it (if you didn'd use mapping, you'd have to do it by hand, property by property).

Your approach of creating a "template viewmodel" with all the properties, so that they exist even if you don't receive it in you JSON responses is good. Besides, it's easier to understand the JavaScript code: you don't need to see the server side to discover which properties are in the view model, as would happen if you made the first mapping directly from the server.

However, if the received model is nearly complete, you can always customize the "create" of your mapping (You could look for missing observable properties using js hasOwnProperty and adding the missing ones). The last example of the docs in the link so precisely how to add a new observable (in this sample, a computed observable):

var myChildModel = function(data) {
  ko.mapping.fromJS(data, {}, this); // this is the view model

  this.nameLength = ko.computed(function() { // nameLength is added to the vm
      return this.name().length;
  }, this);
}

In this sample you could add the condition to create nameLength only if not present on the received data, like this:

if (!data.hasOwnProperty('nameLength')) { 
   /* add the missing observ. property here */
}

(NOTE: you can also customize the update, if needed).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top