Reputation: 33
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
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