Knockout update of an observable array in html

I am working on Android with jQuery Mobile using Phonegap, using Knockout to load data.

I get the data in order and upload it to the html page according to the foreach data binding that I have in the tags.

When I want to update the data, it just does not do this. It returns only html without bound data, or a dom My applyBinding exception exception exception occurs inside the pagecreate event on the page.

I posted a simple example describing the problem on my SkyDrive - http://sdrv.ms/LpUdLt This is a public example reproducing the problem. viewmodel contains an array containing the array. illuminated by random values. trying to reload a page in jQuery mobile with reloading changepage with new data by pressing the navbar button with dom dom error. I donโ€™t agree that I should not create a virtual machine instance for each pagecreate, I just canโ€™t find a way to implement it so that the data is rewritten in html.

//indexPage.js var wAViewModelInst ; var viewPageIndexContent; $('#pageIndex').live('pagecreate', function (event) { viewPageIndexContent = document.getElementById("pageIndexContent"); wAViewModelInst = new WAViewModel(true); ko.applyBindings(wAViewModelInst, viewPageIndexContent); waHeaderVM.refreshContentData = function () { // wAViewModelInst.updateRowList(); // ko.cleanNode(viewPageIndexContent); // viewPageIndexContent = document.getElementById("pageIndexContent"); //wAViewModelInst = new WAViewModel(true); //ko.applyBindings(wAViewModelInst, viewPageIndexContent); $.mobile.changePage("index.html", { allowSamePageTransition: true, reloadPage: true }); $.mobile.hidePageLoadingMsg(); } } //WAViewModel self.WARowList = ko.observableArray(); self.updateRowList = function () { self.WARowList(self.GetWA()); } //tried the exteding //ko.observableArray.fn.WARowListUpdate = function () { // //create a sub-observable // this.hasItems = ko.observable(); // //update it when the observableArray is updated // this.subscribe(function (newValue) { // this.hasItems(newValue && newValue.length ? true : false); // }, this); // //trigger change to initialize the value // this.valueHasMutated(); // //support chaining by returning the array // return this; //}; 

Is there a way to update html after the first rendering?

adding html code:

 <div id="pageIndex" data-role="page" data-transition="flip" data-theme="e" data-dom-cache="true"> <div id="indexHeader" data-role="header" data-theme="e"> <div data-role="navbar" data-iconpos="right"> <ul> <li><a href="login.html" data-role="tab" data-icon="back" data-bind="click: loadingHandler" class="brighter-text">ื—ื–ืจื”</a></li> <li><a href="#" data-role="tab" data-icon="refresh" data-bind ="click: refreshContentData" >ืจืขื ืŸ</a></li> <li><a href="researchEvent.html" data-role="tab" data-icon="check" id="navBarResearchEventPage" data-bind="click: loadResearchEvent" class="brighter-text">ื‘ื™ืฆื•ืข ื—ืงืจ</a></li> <li><a href="#" data-role="tab" data-icon="grid" class="ui-btn-active brighter-text"> ืกื™ื“ื•ืจ ืขื‘ื•ื“ื”</a></li> </ul> </div> </div> <div id="pageIndexContent" data-role="content" data-theme="e" style="padding-bottom: 52px; height: 570px;"> <h2 data-bind="text:Title" class="brighter-text" style="font-size:22pt;"> </h2> <div data-bind="foreach: WARowList" style="width: 99%; text-align: center"> <div> <table style="float: right; width: 20%; height: 60px;" cellpadding="0" cellspacing="0"> <tr data-bind="visible : FirstRow " style="height: 31px;"> <th class="AlignedHeader"> <label> ืฉืขื” / ืฉื™ืœื•ื˜</label> </th> </tr> <tr data-bind="style: { backgroundColor: Odd() ? '#8CC63F' : '#AFC493' }"> <td style="width: 20%;" data-bind="style: { backgroundColor: IsNew() ? 'yellow' : 'transparent' }"> <input type="button" data-bind="click: ShowSampleDetails, value: ShilutTime , jQueryButtonUIEnableDisable:$data" data-icon="plus" data-iconpos="right"/> </td> </tr> </table> <table style="height: 60px; width: 80%; background-color: #8CC63F;" data-bind="style: { backgroundColor: Odd() ? '#8CC63F' : '#AFC493' }" cellpadding="0" cellspacing="0"> <thead data-bind="if : FirstRow"> <tr data-bind="foreach: CellList"> <th class="AlignedHeader"> <label data-bind="text: Date"> </label> </th> </tr> </thead> <tbody> <tr data-bind="foreach: CellList"> <td style="width: 11.5%;"> <div data-bind="visible:IsPopulated "> <div data-bind="visible: HasDrivers"> <input type="button" data-role="button" data-bind="click: ShowBusDriverList.bind($data , $root) , jQueryButtonUIEnableDisable: $data " data-icon="search" data-iconpos="right" value="ื ื”ื’ื™ื" class="brighter-text" /> </div> <div data-bind="visible: !HasDrivers()"> <input type="button" data-role="button" id="btnNoDriver" disabled="disabled" data-icon="info" data-iconpos="right" value="ืื™ืŸ ื ื”ื’" class="brighter-text" /> </div> </div> <div data-bind="visible: !IsPopulated"> </div> </td> </tr> </tbody> </table> </div> 

etc.

the GetWA function returns an observable array of the warow list. it works the first time the problem reengines the dom object. The dom element is dirty ko and fails.

I tried Luffy's answer:

 var lVM = new loginViewModel(); var footerViewModelLogin = { IsOnline: ko.observable(globalContext.Network()), IsSync: ko.observable(globalContext.Sync()) }; $('#login').live('pagecreate', function (event) { viewLoginContent = document.getElementById("loginContent"); ko.applyBindingsToNode(viewLoginContent, lVM); viewLoginFooter= document.getElementById("footerLogin"); ko.applyBindingsToNode(viewLoginFooter, footerViewModelLogin); }); $('#login').live('pagehide', function (event, ui) { $.mobile.hidePageLoadingMsg(); }); function loginViewModel() { var self = this; try { self.userName = ko.observable(""); self.password = ko.observable(""); self.message = ko.observable(""); self.CleanGlobalContext = function () { ... }; self.Validate = function () { ... }; } catch (e) { if (IsDebug) alert("GlobalContext.prototype.SetMapOverlay " + e.message); if (typeof (console) != 'undefined' && console) console.log("GlobalContext.prototype.SetMapOverlay " + e.message); } } ko.applyBindings(lVM); ko.applyBindings(footerViewModelLogin); 

Knockout fails without snapping an item previously defined for snapping.

+6
source share
3 answers

I misunderstood that you are at a loss. However, I do not understand why you need to re-bind bindings. Please note the following:

  • If you modify the observed array, the necessary templates are re-created to update the consistent user interface. However, you need to update the observalble array either using the observable array functions or by going to the observable new array: obs (newArray).
  • If you need to perform actions after re-rendering ko, you just need to use the afterRender or afterAdd template binding options
  • If you add new jQuery code for mobile devices, you will have to analyze it after creating it, otherwise jquery mobile will not work ... again you can do it in the afterRender function.
  • It is problematic to load an html containing ajax ko bindings through ajax. The right approach is to create this content as a template that you render immediately (not with ajax). Then you request the server to get new json content. Then you can create an instance of the template using, for example, binding.
+2
source

Yes, you can re-bind bindings using the ko.applyBindingsToNode function to a specific dom element.

Check out these examples.

0
source

The solution was to add afterRender to the foreach table binding table. as suggested by Francesco Abruzzese. However, an ajax request was included for async: false. Each time I update the list, I execute some dat-bind = "click: updateRowList", which updates the table. Many thanks to Elad Katz for helping with the generosity.

0
source

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


All Articles