1

I'm trying to use an AJAX JSON request to automatically refresh the data displayed on a page with the latest values from the server.

Here's my javascript:

function ExampleViewModel() { var self = this; self.ExampleData = ko.observableArray([]); $.getJSON("/JSONExample", function (allData) { var mappeddata = $.map(allData, function (item){ return new DataItem(item) }); self.ExampleData(mappeddata); }) window.setTimeout(ExampleViewModel, 5000); } function DataItem(data) { //console.log(data); this.Name = ko.observable(data.Name); this.Price = ko.observable(data.Price); } ko.applyBindings(new ExampleViewModel()); 

And here's my HTML:

<div id="knockout"> <table> <thead> <tr> <th>Name</th><th>Price</th> </tr> </thead> <tbody data-bind="foreach: ExampleData"> <tr> <td data-bind="text: Name"></td> <td data-bind="text: Price"></td> </tr> </tbody> </table> </div> 

It's correctly pulling the JSON and it displays correctly on the first iteration. The output looks like this:

Name Price Item1 $150.00 Item2 $20.00 Item3 $99.99 

On subsequent iterations, it pulls the JSON, and if I change the data on the server (say if I change the price of Item1 to $200.00), it does get the updated data in the JSON. However, the UI doesn't refresh - it just displays the initial data until I refresh the whole page.

I believe I'm misunderstanding something about how the knockout bindings work, or else my approach is totally off for what I'm trying to do.

1 Answer 1

4

Checkout demo

You have to keep instance of ExampleViewModel and use that instance for everything.

function getRandomData() { return [{ "Name": "Apple", "Price": (Math.random()*10)+1}, { "Name": "Orange", "Price":(Math.random()*10)+1}, { "Name": "Banana", "Price": (Math.random()*10)+1}, { "Name": "Melon", "Price": (Math.random()*10)+1}]; } function ExampleViewModel() { var self = this; self.ExampleData = ko.observableArray([]); self.update = function() { $.ajax("/echo/json/", { data: { json: ko.toJSON(getRandomData()) }, type: "POST", dataType: 'json', success: function(allData) { var mappeddata = $.map(allData, function (item){ return new DataItem(item) }); self.ExampleData(mappeddata); } }); } } function DataItem(data) { //console.log(data); this.Name = ko.observable(data.Name); this.Price = ko.observable(data.Price); } var exampleViewModel = new ExampleViewModel(); window.setInterval(exampleViewModel.update,1000); ko.applyBindings(exampleViewModel); 

Also beware of using this keyword directly inside the callback function of setTimeout & Interval. Use 'self' instead. Checkout this problem part

Sign up to request clarification or add additional context in comments.

1 Comment

Ah now I get what I was doing wrong. This worked like a charm thanks!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.