2011-07-18 73 views
18

我們使用knockout和knockout貼圖插件來促進我們的jQTouch web應用程序中的數據綁定。我們使用映射插件的原因是能夠使用knockout,而無需在javascript中手動定義/更改視圖模型。當您從服務器/客戶端數據庫初始加載數據時,映射插件很有用。Knockout JS映射插件沒有初始數據/空格式

我們遇到的問題是,我們有一些屏幕/視圖的形式可能沒有任何初始數據。沒有這個初始數據,映射插件不能'生成'視圖模型(ko.mapping.fromJS)。這意味着我們仍然需要爲大部分視圖手動定義我們的視圖模型。

我錯了,假設這是一個映射插件(應該)支持的場景嗎?我的意思是,這意味着映射插件僅適用於您始終具有初始數據加載的情況。

回答

19

除了手動管理視圖模型之外,還有幾個選項可供選擇。映射插件支持create回調,可讓您自定義它的創建方式。這可用於將缺省屬性添加到對象,如果它們碰巧缺失。

事情是這樣的:http://jsfiddle.net/rniemeyer/WQGVC/

另一種方法是使用綁定創建缺少的屬性。它看起來像:

//create an observable if it does not exist and populate it with the input's value 
ko.bindingHandlers.valueWithInit = { 
    init: function(element, valueAccessor, allBindingsAccessor, data) { 
     var property = valueAccessor(), 
      value = element.value; 

     //create the observable, if it doesn't exist 
     if (!ko.isWriteableObservable(data[property])) { 
      data[property] = ko.observable(); 
     } 

     //populate the observable with the element's value (could be optional) 
     data[property](value); 

     ko.applyBindingsToNode(element, { value: data[property] }); 
    } 
} 

你會使用這樣的(需要物業作爲一個字符串傳遞,否則會報錯):

<input data-bind="valueWithInit: 'name'" /> 

樣品在這裏:http://jsfiddle.net/rniemeyer/JPYLp/

+0

由於RP尼邁耶,我會在接下來的幾天內嘗試了這一點。聽起來很有希望! – MichaelvR

+0

自定義裝訂完美,謝謝! – MichaelvR

+1

的卡斯特init已綁定爲我工作不錯,但我不喜歡數據綁定屬性的綁定的動態更新的,所以我建議使用[virual元素(http://knockoutjs.com/documentation/custom-bindings - 用於虛elements.html)。 \t \t 喜歡的東西: < - KO valueWithInit: 'PropC' - > <輸入數據綁定= 「可見:PropC,值:PropC」> –

4

我認爲解決您的問題來自以錯誤的方式考慮視圖模型。視圖模型不僅是將數據傳遞給視圖的東西,還是將數據提交回來的佔位符。

我通常最終與knockout合作的方式,我從來沒有最終發送一個空視圖模型到視圖。視圖模型通常具有我綁定的所有字段。儘管它們可能是空字符串,或者是沒有顯示值的初始化對象,但實際的對象仍然會退出,並且每個對象都有適當的表示來與我綁定的字段相關聯。

您可能想要簡單地向視圖發送空對象而不是任何內容。

編輯:這個例子是未ASP.NET MVC

所以basiclaly,我在服務器端,我創建視圖模型對象,其中包含所有需要被顯示的數據以及所有數據需要收集。爲了更簡單的驗證代碼,我通常會將數據收集到它自己的子類中,但這都是代碼需求的問題。

在任何情況下,任何對象都會從vmBase類中獲取inherts,它基本上提供了一個生成對象的JSON序列化的toJSON()方法。這在視圖引擎的視圖中被調用。如下面的代碼所示。

 <script type='text/javascript'>   
     var viewModel = ko.mapping.fromJS(<%= Model.ToJson() %>);      

     $(document).ready(function() {   
      ko.applyBindings(viewModel);        
     });     
    </script> 

當我準備發回代碼時,我只需刪除一個JS版本的視圖模型。

<script type='text/javascript'> 
    var dataToSendToServer = ko.toJS(viewModel); 
</script> 

在某些sanarios,其中只有視圖模型的一部分被改變(這是如果你正在做AJAX更新),你可以做一些很酷的東西一樣,切換模板,以便不同的結合可以applyed。在這種情況下,我們使用的是#ID_of_Container作爲原始數據/模板的容器和更換模板(其可以包含數據綁定=「」元件)的新模板ID_of_Template

<script type='text/javascript'> 
    ko.cleanNode($("#ID_of_Container")); 
    delete (viewModel.Some_Element_To_Be_Updated); 
    viewModel = ko.mapping.updateFromJS(viewModel, New_Data_For_That_Element); 

    // Use ko.toJS(viewModel) because standard template plugin doesn't understand 
    // knockout observables 
    $("#ID_of_Container").html($("#ID_of_Template").tmpl(ko.toJS(viewModel))) 
    ko.applyBindings(viewModel, $("#ID_of_Container")[0]); 

</script> 
+0

你也使用KO映射插件嗎?這使您可以生成視圖模型,而不必手動定義它。這是我們遇到問題的部分。 – MichaelvR

+0

希望編輯有幫助。這讓我有點意識到,我可以用淘汰賽做這種類型的東西。它結束了一些相當不錯的結果。它確實給網站一個厚厚的客戶端下了很多流暢的AJAX流量。 –

0

一種方法我現在正在探索是創建一個名爲ReturnEmptyObject(),它什麼都不做比創建其他額外的Web服務方法,並返回一個新實例化對象(其屬性將是默認值)在服務器端。在(對我來說C#)對象被序列化到JSON,終於到達了jQuery Ajax調用....然後傳遞到ko.mapping.updateFromJS()...它創建的初始頁面加載所需的觀測..在我調用ko.applyBindings()之前。

當ko.applyBindings()執行,它認爲有需要,所以它不會拋出一個錯誤,即使他們大多是空的觀測。

這樣的頁面可以開始沒有任何填充字段,如果我增加一些新的屬性,我在服務器端類被打開。然而,它們會自動在客戶端上顯示仍然。