3

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).

1
  • It would help if you show us what your model is like, and a few more bits of your view (specifically: the template). Commented May 18, 2013 at 8:55

2 Answers 2

2

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}">
Sign up to request clarification or add additional context in comments.

Comments

1

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:

Option 1

<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.

Option 2

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?
  • you use a specific 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.