user1959772
user1959772

Reputation: 33

Dynamic View Model

How do you build a dynamical view model from JS objects returned through Ajax?

When creating an observable object and and observable array, the view contains no data, unless bound after every get, causing the alert to be bound multiple times.

My JS

var SummaryData = {
  Summary: {
    Count: 4
  }
};

var DetailsData = {
  Status: [{
    Name: "One",
    Type: 1
  }, {
    Name: "Two",
    Type: 1
  }, {
    Name: "Three",
    Type: 0,
    Taco: "True"
  }]
};
var self = this;
self.Summary = new ko.observableArray([]);
self.Details = ko.observable();
self.Load = function () {

$.ajax({
      url: "/echo/json/",
      data: SummaryData,
      type: "GET",
      success: function (data) {
        // Map the returned JSON to the View Model  
        self.Summary = ko.mapping.fromJS(data.Summary);
      }
})
$.ajax({
      url: "/echo/json/",
      data: DetailsData,
      type: "GET",
      success: function (data) {
        // Map the returned JSON to the View Model  
        self.Details = ko.mapping.fromJS(data.Status);
      }
})

My HTML:

<span data-bind="text: Summary.Count"></span>
<table data-bind="foreach: Details">
    <tr>
        <td data-bind="text: Name"></td>
        <td><button data-bind="click: $root.Clicked"></button></td>
    </tr>
</table>

http://jsfiddle.net/atwoodkevin/q8EKP/40/

Upvotes: 1

Views: 2483

Answers (1)

John Earles
John Earles

Reputation: 7194

The key is to initialize the observables and judiciously use bindings (such as with, if, and foreach) that will not bind child elements until a non-null value is set in the observable. Set observables (using the () form), instead of redefining, when you get data via AJAX. Mapping straight arrays (i.e. not embedded in an object) can be handled slightly differently, initialized by calling ko.mapping with an empty array and then updating the mapping with ko.mapping.fromJS(data.Status, self.Details)

Two other points:

Since you pass View.Load() into ko.applyBindings that you have to return your ViewModel from that method.

Your Clicked handler should be inside the ViewModel.

--

Here is a functioning fiddle: http://jsfiddle.net/jearles/q8EKP/43/

Upvotes: 1

Related Questions