Knockout.js - refresh the page every 5 seconds with a new value

I just look in knockout.js with the MVC-Web-API and I am trying to create a Hello World page that will update the time on the page every 5 seconds. It makes a call every 5 seconds, I see it in my controller (breakpoint), but nothing is displayed on the screen.

UPDATE: I am still working on this, and now I have established that I return data from the server, the call is made by the controller every 5 seconds, and it returns the JSON I need (warnings show this) however, nothing is displayed on the span element on the page yet.

I really need to use the mapping function, as I am developing a larger website that has a model with more than 50 properties and doesn’t particularly want to go through and display them separately in the viewmodel.

I have included my code below.

<span data-bind="text: TimeString"></span> <script type="text/javascript"> var viewModel; var getUpdates = setInterval(function () { $.getJSON( "/Values/Get", {}, function (model) { alert(model.TimeString); ko.mapping.fromJS(model, viewModel); }); }, 5000); $(document).ready( function () { $.getJSON( "/Values/Get", {}, function (model) { var viewModel = ko.mapping.fromJS(model); alert(model.TimeString); ko.applyBindings(viewModel); }); }); function bindViewModel(model) { ko.applyBindings(model); } 

 public class HelloWorldModel { public DateTime TimeDT { get; set; } public String TimeString { get; set; } } public class ValuesController : Controller { public HelloWorldModel Model = new HelloWorldModel(); [System.Web.Mvc.AcceptVerbs(HttpVerbs.Get)] public JsonResult Get() { Model.TimeDT = DateTime.Now; Model.TimeString = Model.TimeDT.ToString("HH:mm:ss"); return Json(Model, JsonRequestBehavior.AllowGet); } // POST api/values public void Post([FromBody]string value) { } // PUT api/values/5 public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 public void Delete(int id) { } } } 
+6
source share
3 answers

If you follow the documentation , this should not be too complicated. On the first call to the server, do:

 var viewModel = ko.mapping.fromJS(model); ko.applyBindings(viewModel); 

You apply bindings to the JS object (getJSON returns a JS object, not a JSON string if I read the documentation correctly).

After that, in your repeating function, do:

 ko.mapping.fromJS(model, viewModel); 

From the documentation:

  • All object properties are converted to observables. If the update changes the value, it will update the observable.
  • Arrays are converted to observable arrays. If the update changes the number of elements, it will perform the corresponding addition / removal of the action. It will also try to maintain order in the same way as the original JavaScript array.
+6
source

You do not need to replace the full view model and instead can update the properties returned from your Ajax request, for example:

 $(function() { var vm = { TimeDT: ko.observable(), TimeString: ko.observable() }; function updateValues() { $.getJSON("/Values/Get").done(function(data) { vm.TimeDT(data.TimeDT); vm.TimeString(data.TimeString); }); } ko.applyBindings(vm); updateValues(); setInterval(updateValues, 5000); }); 

You can see here a small example that I made in JsFiddle.

+4
source

Disclaimer: I work with Ben.

There are several problems with the code, firstly, you are missing some JavaScript links, and secondly, the viewModel is always zero every time the timer passes through.

You need to download the Javascript file for matching knockouts from here , name it knockout.mapping-latest.js and save it in the scripts directory. Then make sure to add links to jquery and knockout.js.

The updated Razor view is shown below:

 <div id="body"> <span data-bind='text: TimeString'></span> <script src="~/Scripts/jquery-1.8.2.js" type="text/javascript"></script> <script src="~/Scripts/knockout-2.2.0.debug.js" type="text/javascript"></script> <script src="~/Scripts/knockout.mapping-latest.js" type="text/javascript"></script> <script type="text/javascript"> var viewModel; var getUpdates = setInterval(function () { $.getJSON( "/Values/Get", {}, function (model) { //alert(model.TimeString); ko.mapping.fromJS(model, viewModel); }); }, 5000); var viewModelSet = false; $(document).ready( function () { $.getJSON( "/Values/Get", {}, function (model) { viewModel = ko.mapping.fromJS(model); ko.applyBindings(viewModel); }); }); function bindViewModel(model) { ko.applyBindings(model); } </script> </div> 

Just to add public fields in a class, there is usually no-go, in your ViewModeM your instance of HelloWorldModel does not get access anywhere in the code, only inside this class, so it can be private. If accessed from other sources, it would be best practice to keep him confidential and expose him through property. More details here .

+3
source

Source: https://habr.com/ru/post/948723/


All Articles