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>
The key is to initialize the observables and judiciously use bindings (such as
with,if, andforeach) 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 callingko.mappingwith an empty array and then updating the mapping withko.mapping.fromJS(data.Status, self.Details)Two other points:
Since you pass
View.Load()intoko.applyBindingsthat you have to return your ViewModel from that method.Your
Clickedhandler should be inside the ViewModel.—
Here is a functioning fiddle: http://jsfiddle.net/jearles/q8EKP/43/