2012-06-25 223 views
6

我正在使用帶有Phonegap的Jquery Mobile使用Knockout加載數據。Knockout刷新html中的observableArray

我得到的數據所有權利,並加載到html頁面根據我對標籤的foreach數據綁定。

當我想刷新數據,它只是不這樣做。 它只返回一個沒有綁定數據的html或拋出dom異常未找到 我的applyBinding發生在頁面的pagecreate事件內部。

我已經發布了一個簡單的例子來描述我的SkyDrive上的問題 - http://sdrv.ms/LpUdLt 這是公共示例,重現問題。 viewmodel保存包含數組的數組。用隨機數值刷新 。 試圖重新加載頁面在jquery移動與變化頁面重新加載與新的數據通過按導航欄按鈕失敗與dom對象的錯誤。 我同意不會這樣做,我不應該創建每個pagecreate虛擬機的實例,只是不能找到實現它的方式,以便數據將在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; 
    //};    

有沒有辦法在第一次渲染後更新html?

添加HTML代碼:

<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> 

等..

的GetWA函數返回warow列表的observableArray。 這是第一次麻煩重新渲染dom對象。 的DOM元素污染有KO和失敗..

我試圖路飛的答案:無結合元件預定事件

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); 

敲除失敗。

+0

你能告訴我們更多的代碼,比如HTML或者GetWA方法嗎?當你說'它只返回空的HTML'時,被調用的是什麼返回空的HTML? – CodeThug

+0

問題是否有重新應用綁定的方法? viewModel中的observabeArray的重新初始化不會重新組織和重新繪製視圖。 –

+0

我已更正後 - 它不返回emty html - 它返回一個沒有刷新viewmodel的數據綁定信息的HTML。 –

回答

0

是的,你可以重新使用ko.applyBindingsToNode函數綁定到特定的dom元素。

檢查這些例子

  1. http://jsfiddle.net/rniemeyer/gYk6f/ --->隨着模板
  2. http://jsfiddle.net/rniemeyer/BnDh6/ --->隨着數據 - 值對
+0

我會嘗試它,但問題是它是一個observableArray嵌套的observableArrays。它是一樣的嗎? –

+0

它沒有通過應用綁定沒有定義的元素 –

2

我沒有很好理解你的困難。但是,我不明白你爲什麼需要重新綁定綁定。請注意以下內容:

  1. 如果更改了可觀察數組,則需要重新實例化模板以更新連貫的UI。但是,您必須通過使用observable數組函數來更新可觀察數組,或者通過傳遞給observable一個新數組:obs(newArray)。
  2. 如果您需要在ko重新呈現後執行操作,您只需要使用模板綁定的afterRender或afterAdd參數,如果添加了新的jquery移動代碼,則必須在創建它之後解析它,否則jquery mobile將無法工作......再次,您可以在afterRender功能中執行此操作。
  3. 通過ajax加載包含ajax ko綁定的html是有問題的。正確的做法是將該內容創建爲模板,並立即渲染(而不是使用ajax)。然後,您只需查詢服務器即可獲取新的json內容。然後,您可以通過使用例如with綁定來實例化模板。
+0

1.I用新數據重新啓動了可觀察數組,但是所需的模板不會重新實例化以更新連貫的UI。實際上,它只是向我顯示了根本沒有數據的html。 2.afterRender我需要爲可觀察數組創建更新綁定處理程序? 3.每次我在jqm頁面,在第一次applyBinding DOM後「元素」不能重新初始化。多數民衆贊成在問題 –

+0

也許有一些錯誤的地方...我使用了很多模板...我從來沒有類似的問題...但是當我使用jquery移動版淘汰賽時,我預先載入所有頁面,並且只需在json中與服務器通信...我下載了您的代碼...讓我一看。如果我可以刷新其中的ko數據, –

+0

預加載將是最佳選擇。 –

0

解決的辦法是在foreach表中添加afterRender數據綁定。正如 - Francesco Abbruzzese所建議的那樣。 雖然ajax請求已被轉換爲async:false。 每次我更新列表時,我都會執行一些更新表的dat-bind =「click:updateRowList」。 非常感謝Elad Katz對賞金的幫助。

+0

您好,我認爲解決方案是使用您建議的afterRender。儘管如此。我已經刪除了afterRender和應用程序更新本身。 問題在於處理現有列表中的值,並用新數據重新初始化值。 –