2017-08-01 76 views
0

我遇到了這種情況,當下拉從可計算的KO屬性更改時,下拉的綁定值observable不會自動同步。 這是一個有點棘手,因爲下拉列表是從另一個下拉列表中選擇一個值填充,而是爲了使這更清楚我創造了這個測試搗鼓這表明了問題:https://jsfiddle.net/n3wjack/gzmb792p/KO綁定值與下拉不同步

這裏是如何模擬問題:

  • 在寵物下拉列表中,選擇John的第二隻寵物「Mozart」。你會看到'selected寵物'標籤更新。
  • 現在在第一個下拉列表中選擇簡。第二個下拉列表將更新,顯示Jane的寵物。

選定的寵物標籤是未更新顯示簡的第一個寵物的名稱。 如果您對寵物下拉列表進行更改,則該值會再次更新。 我不能保證用戶會這樣做,所以我不確定這個值是否正確。

那麼我該如何解決這個問題,或者我做錯了什麼?

-

我還包括下面的代碼,顯然這是必需的。

JS:

var petOwners = [ 
    { name: "John", pets: ["Blacky","Mozart"] }, 
    { name: "Jane", pets: ["Polly", "Felix"]} 
]; 

var viewModel = { 

    availableOwners: ko.observableArray(petOwners), 
    selectedOwner: ko.observable(), 

    selectedPet: ko.observable() 
} 

viewModel.availablePets = ko.computed(function(){ 
    console.log("** availablePets computed **") 
    var result = []; 
    if (viewModel.selectedOwner()) 
    { 
     console.log(viewModel.selectedOwner()); 
     result = viewModel.selectedOwner().pets;  
    } 

    console.log(result); 
    return result; 
    }, this); 

viewModel.peekPet = function(){ 
    document.getElementById("peekoutput").innerHTML += "selectedPet = " + viewModel.selectedPet.peek() + "</br>"; 
} 

ko.applyBindings(viewModel); 

HTML:

<select data-bind="foreach:availableOwners, value:selectedOwner"> 
    <option data-bind="text: name, value: $data"></option> 
</select> 
<i> 
(selected: <span data-bind="text: selectedOwner().name"></span>) 
</i> 

<p> 
This dropdown shows the pets of the owner, selected in the above dropdown. 
</p> 
<select data-bind="foreach:availablePets, value: selectedPet"> 
    <option data-bind="text: $data, value: $data"></option> 
</select> 

<p> 
<i> 
Selected pet: <span data-bind="text: selectedPet"></span> 
</i> 
</p> 
<p> 
The selected pet however doesn't update to be in sync with the first pet in the dropdown, when you change the owner dropdown. :(
</p> 

<p> 
<button data-bind="click: peekPet">Peek selected pet</button> 
</p> 

<code id="peekoutput"> 
</code> 
+0

你應該使用'options'結合,而不是'的foreach '。 –

回答

1

所有你需要做的是訂閱選定的所有者的變化:

var viewModel = { 
    availableOwners: ko.observableArray(petOwners), 
    selectedOwner: ko.observable(), 
    selectedPet: ko.observable() 
} 

viewModel.selectedOwner.subscribe(function(){ 
    if(viewModel.selectedOwner().pets.length > 0) { 
     viewModel.selectedPet(viewModel.selectedOwner().pets[0]); 
    } 
}); 

UPDATED JSFIDDLE

還有一個替代的選擇與集合的選擇,這將同步無簽約綁定:

<select data-bind="options: availablePets, optionsText: $data, optionsValue: $data, value: selectedPet"></select> 

https://jsfiddle.net/gzmb792p/18/

+0

確實使用選項綁定工作。有趣。我習慣於使用foreach語法,但顯然KO的行爲似乎與使用該選項綁定時不同。我想這就是它的意思。 只要你保持簡單,foreach就可以工作。但在我的情況下,第一個事件出現了錯誤。 – n3wjack

0

這是因爲當它刷新列表,你沒有選擇任何寵物。默認情況下,它顯示第一個,但並不意味着他被選中。

您可以添加的指令實際上選擇列表中的第一個:

viewModel.availablePets = ko.computed(function(){ 
    console.log("** availablePets computed **") 
    var result = []; 

    if (viewModel.selectedOwner()) 
    { 
     console.log(viewModel.selectedOwner()); 
     result = viewModel.selectedOwner().pets; 

     //something like this to mark your first pet as selected. 
     viewModel.selectedPet(result[0]);  
    } 

    console.log(result); 
    return result; 
}, this); 
+0

也嘗試過,奇怪的是它不起作用。我更新了小提琴,你甚至可以在日誌中看到它設置的值,但綁定不會更新:https://jsfiddle.net/n3wjack/gzmb792p/15/ – n3wjack

+0

這可能無法正常工作,因爲它拒絕設置選定的寵物,甚至沒有選擇,因爲可用的寵物不會更新,直到返回結果。 –

+0

這很有道理。我也在思考這個問題。它似乎確實拒絕編輯。 – n3wjack

1

這裏是一個不同的方法。 pet主成爲一組對象。那麼你使用選項綁定。這裏是小提琴。

https://jsfiddle.net/0o89pmju/22/

的JavaScript

var petOwners = [{ 
    name: "John", 
    pets: ["Blacky", "Mozart"] 
}, { 
    name: "Jane", 
    pets: ["Polly", "Felix"] 
}]; 

function petOwner(data) { 
    var self = this; 
    this.name = ko.observable(data.name); 
    this.selectedPet = ko.observable(''); 
    this.pets = ko.observableArray(data.pets); 
} 

function viewModel() { 
    var self = this; 
    this.petOwners = ko.observableArray(''); 
    this.selectedPetOwner = ko.observable(''); 
} 


var vm = new viewModel(); 


(function($) { 
    ko.applyBindings(vm); //bind the knockout model 
    $.each(petOwners, function(i, item) { 
    vm.petOwners.push(new petOwner(item)); 
    }); 
    console.log(ko.toJS(vm)); 
})(jQuery); 

HTML

choose a pet owner: 
<select data-bind="options: petOwners, 
         optionsText: 'name', 
         value: selectedPetOwner, 
         optionsCaption: 'Choose...'"></select> 

<div data-bind="with: selectedPetOwner"> 
    Choose a pet: 
    <select data-bind="options: pets, value: selectedPet"></select> 
</div>