Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use knockout.js data binding when ajax request periodically auto refreshes?

In my application I periodically makes ajax call once every 5 seconds to get new update from server.

My ajax data from server is JSON array that looks like: [ { "foo": "valx", "bar": "valy"

}, { "foo": "valw", "bar": "valz" } ]

My ajax code is:

(function update() {

    $.ajax({
        type : 'GET',
        url : url,
        data : {

        },
        dataType : "json",
        global : false,
        success : function(content, textStatus, jqXHR) {
        myViewModel = content;
        ko.applyBindings(myViewModel);

        },
        complete: function() {

         setTimeout(update, 5000);
          },

        error: function( xhr, textStatus ) {

            }
    });
    })();                       

My HTML is:

<tbody data-bind="foreach: myViewModel">
                        <tr>
                            <td data-bind="text: foo"></td>
                            <td data-bind="text: bar"></td>
                        </tr>
                    </tbody>

But this does not work and I get error after first ajax call: You cannot apply bindings multiple times to the same element.

like image 468
rjc Avatar asked Dec 10 '13 00:12

rjc


People also ask

Is debugging difficult in Ajax?

It's very difficult to debug an AJAX request using the jQuery's shorthand AJAX methods because these methods don't give you a full control over the request.

What is deferred in knockout JS?

Deferred – Notifications happen asynchronously, immediately after the current task and generally before any UI redraws. Rate-limited – Notifications happen after the specified period of time (a minimum of 2-10 ms depending on the browser).

What is binding in knockout JS?

A binding context is an object that holds data that you can reference from your bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. The root level of the hierarchy refers to the viewModel parameter you supplied to ko. applyBindings(viewModel) .


1 Answers

You're close. You only call applyBindings once. Instead what you should be doing is setting an observable property on your view model.

Here is how you would setup your view model:

function ViewModel() {
    var self = this;

    self.data = ko.observableArray();
};

var viewModel = new ViewModel();

ko.applyBindings(viewModel);

Then when you have new data (e.g. in your ajax call):

$.ajax({
    success : function(content, textStatus, jqXHR) {
        viewModel.data(content);
    }
});

Note: You could set the data a few different ways. If you want your timed event outside the view model then you can use the view model instance (in my example, viewModel) to access the properties and update them. You could place the timed event within your view model if you want and then just call self.data(content) (or something similar).

like image 97
Justin Helgerson Avatar answered Oct 26 '22 20:10

Justin Helgerson