2012-02-06 97 views
2

我正在用Knockout.js構建一個簡單的應用程序作爲概念驗證。由於我對Knockout非常陌生,因此這個問題中的代碼可能遠非完美並且表現出不好的做法,所以請隨時告訴我是否屬於這種情況!KnockoutJS選項與重複值綁定

我使用options結合產生select元素的內容:

<select data-bind="options: titles, optionsText: 'display', optionsValue: 'value'"> 
</select> 

視圖模型看起來是這樣的:

var ViewModel = function() { 
    this.titles = ko.observableArray([]); 
}; 

在DOM準備好我推一些值該可觀察數組(每個值是對象字面值,表示「標題」,例如「Mr」,「Mrs」等):

var data = [ 
    { value: "Mr", display: "Default Value" }, 
    { value: "Miss", display: "Miss" }, 
    { value: "Mr", display: "Mr" }, 
    { value: "Ms", display: "Ms" } 
]; 
ko.applyBindings(view); 
for(var i = 0; i < data.length; i++) { 
    view.titles.push(data[i]); //Push titles into observable array 
} 

不要問爲什麼有兩個對象的值爲「Mr」,這就是我必須處理的數據的來源。我無法改變它。但是,這是導致問題的原因。我期望第一個對象代表選定的選項,但事實並非如此。第三個對象表示實際結束的option元素作爲默認選擇。

我相信這是由於可觀察數組導致option元素在循環迭代時被逐個添加到DOM。敲除嘗試通過檢查它的值來保留選定的選項。在第一次迭代之後,所選的option具有值「Mr」。在第三次迭代之後,另一個option的值爲「Mr」,所以Knockout認爲它是之前選擇的選項並將其選中。

這是一個link to a fiddle顯示問題。應該選擇「默認值」選項,但不是。如果單擊該按鈕再次添加具有相同值的另一個選項,該選項將變爲選中狀態,但根據文檔,該選項不應該這樣。

我的問題是,如何防止這種行爲?

回答

3

爲什麼你要將物品逐一放入數組中?你可以只是做:的

view.titles(data); 

代替

for(var i = 0; i < data.length; i++) { 
    view.titles.push(data[i]); //Push titles into observable array 
} 

這也將解決您的問題 - 第一個項目將被默認選擇。此外,如果您不打算向該陣列添加新項目,則可以使用ko.observable而不是ko.observableArray

更新: Knockoutjs似乎不喜歡具有相同值的多個選項。如果您將值綁定添加到選擇標籤(它將選擇第三項,而不是第一項),我的代碼將無法正常工作。但是,由於knockoutjs允許你通過值綁定來訪問選中的對象,所以你可以通過值綁定去除optionsValue綁定和訪問值:jsfiddle.net/ej9Ue/1

+0

啊,是的,它確實在最初修復它。但是當你添加新的選項時,它並沒有幫助。看到這個更新的小提琴:http://jsfiddle.net/YuQsz/2/當點擊「添加」時,「默認值」應該保持選擇,但不是。 – 2012-02-06 16:24:45

+0

這肯定解決了初始數據的問題,但原始問題突出顯示了Knockout.js選擇先前選擇的選項的方式中的怪癖/缺陷。它只檢查元素的值,如果多個選項具有相同的值(這是一個有效的用例),它可以選擇錯誤的值。一個可能的解決方案是在決定匹配之前檢查價值並顯示文本。這通過添加具有相同值的新選項而突出顯示,但顯示文本不同。 – adpd 2012-02-06 16:25:13

+0

你說得對,knockoutjs似乎並不喜歡具有相同價值的多個選項。如果您將值綁定添加到選擇標籤(它將選擇第三項,而不是第一項),我的代碼將無法正常工作。但是,由於knockoutjs允許你通過值綁定來訪問選中的對象,你可以通過值綁定來移除optionsValue綁定和訪問值:http://jsfiddle.net/ej9Ue/1/ – 2012-02-06 17:26:39