1

I have the following snippet JQuery inside an HTML file:

$.getJSON("/events/", function (data) {
    viewModel = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);
});

The code is executed when, for example, the user presses a button and returns JSON like:

{"Events":[{"Name":"Event1"},{"Name":"Event2"},{"Name":"Event3"}]}

This result is linked (using KnockoutJS) to:

<ul data-bind="foreach: Events">
    <li><span data-bind="text: Name"></span></li>
</ul>

Everything works fine with the first call to $.GetJSON. I get what I want, which is (browser output):

  • Event1
  • Event2
  • Event3

But in subsequent calls to "$. GetJSON" I get the following error in Firebug:

NotFoundError: Node was not found.

containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);

And I get no list item.

What I can be doing wrong?

Thank you very much in advance.

Sebastián Guerrero
  • 1,055
  • 1
  • 19
  • 26

2 Answers2

1

My friend Thomas Brattli found the solution:

<ul data-bind="template: { name: 'template', foreach: Events }"></ul>

<script id="template" type="text/html">
    <li><span data-bind="text: Name"></span></li>
</script>

Thanks !

Sebastián Guerrero
  • 1,055
  • 1
  • 19
  • 26
  • 1
    Your solution may work (using a named template), but the real problem is that you're calling `ko.applyBindings` multiple times on the same view. This isn't supported by Knockout and will inevitably cause problems. – Michael Best Sep 19 '12 at 22:44
  • Thanks Michael! How do you think it would be better to implement in this case? – Sebastián Guerrero Sep 19 '12 at 23:40
1

The whole point of Knockout is to handle the interaction between your view and view model. In this case, you're trying to update a list of events in response to a button click. The button click should be linked to a function in your view model, while the list should be linked to an observable array that's updated when you click the button. I've put this together in a fiddle here: http://jsfiddle.net/mbest/uZb3e/ and the important parts are below:

<button type=button data-bind="click: updateEvents">Update</button>
<ul data-bind="foreach: data.Events">
    <li><span data-bind="text: Name"></span></li>
</ul>

Javascript:

var viewModel = {
    data: ko.mapping.fromJS({"Events":[]}),
    updateEvents: function() {
        var self = this;
        $.getJSON("/events/", function (data) {
            ko.mapping.fromJS(newData, self.data);
        });​
    }
};

ko.applyBindings(viewModel);​
Michael Best
  • 16,623
  • 1
  • 37
  • 70