Reputation: 2114
I have an AJAX request that returns an array of objects (Results). In the success callback function, the binding is applied using:
success: function(data) {
ko.applyBindings(new ResultsViewModel(data), target);
}
Where target
is the target DOM element, and ResultsViewModel
is created similar to:
function ResultsViewModel(model) {
var self = this;
self.text = ko.observable(model.text);
self.id = model.id;
self.Descriptions = ko.observableArray(model.descriptions);
}
In my HTML, the data is bound to the elements using:
<div data-bind="template: {name: 'results-template', foreach: $data}">
Then a template class that binds the individual properties of the view model.
My question is: how can I bind the array of data that is returned by my AJAX call (multiple result objects) using the viewmodel with a mixture of observable and static properties to the DOM?
The foreach loop I am using should create a template and bind each object in the returned array to a separate div, but it looks as though it is attempting to bind the root object in the returned array, which is null (unnamed array).
Upvotes: 3
Views: 1373
Reputation: 63709
We can (somewhat) see where you're going with this. Your question is not 100% clear, so it's impossible to give a definitive answer (I suggest going through the KnockoutJS tutorials because you seem to have a few basic KO concepts mixed up). Nonetheless, here's one direction you could take.
As mentioned in the other answer, you use the template
binding, but you don't indicate why you'd need that, as the foreach
binding should suffice. The data for that template would be the Descriptions
observable array, not $data
. You're entire View (when keeping the use of the template
binding) should look like something like this:
<script type="text/html" id="results-template">
<span data-bind="text: desc"></span><br />
</script>
<h4 data-bind="text: text"></h4>
<div data-bind="template: {name: 'results-template', foreach: Descriptions}">
</div>
This is assuming your Descriptions
are complex objects that look like this:
[{ id: 12, desc: "Feels good" }, ... ]
See this fiddle for a demo.
If your descriptions are just flat strings then your View's template needs to change and it does use the $data
variable:
<script type="text/html" id="results-template">
<span data-bind="text: $data"></span><br />
</script>
This is assuming your data looks like this:
["Feels good", ... ]
See this fiddle for a demo.
As a footnote, I noticed:
self.id
is no observable, is that intentional?target
when applying bindings, but from your question I see no reason why you'd need that?In my example fiddle I've changed those two things.
Upvotes: 1
Reputation: 10989
It looks like you're misusing the $data
"special context property" (as the knockout.js docs calls it). Quoting:
But what if you want to refer to the array entry itself (not just one of its properties)? In that case, you can use the special context property $data. Within a foreach block, it means “the current item”.
You're not really using a foreach
binding, though: it's a template binding. In the docs for the template binding, they never use the foreach: $data
syntax, it's always foreach: somePropOnTheViewModel
.
Have you tried doing that instead? I can't be certain if this will do what you want without seeing the rest of the HTML for the binding you're applying it to, but I think this would work for your template code:
<div data-bind="template: {name: 'results-template', foreach: Descriptions}">
Upvotes: 2