2017-08-01 1 views
0

ドロップダウンが計算可能なKOプロパティから変更されたときに、ドロップダウンのバウンド値観測値が自動的に同期されないこのケースが発生します。 ドロップダウンが別のドロップダウンリストで選択した値から移入されたが、私は、問題を示し、このテストフィドルを作成し、これはより明確にするためので、それは少しトリッキーです:https://jsfiddle.net/n3wjack/gzmb792p/KOバウンド値がドロップダウンと同期しない

は、ここで問題をシミュレートする方法は次のとおりです。

  • ペットのドロップダウンで、Johnの2番目のペットである「Mozart」を選択します。 「選択したペット」ラベルの更新が表示されます。
  • 最初のドロップダウンでJaneを選択します。 2番目のドロップダウンが更新され、ジェーンのペットが表示されます。

選択したペットラベルはです。には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

あなたはむしろforeachの ''よりoptions'バインディングを使用する必要があります'。 –

答えて

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は、単純なままにしておく限り動作します。しかし、私の場合、2番目のドロップダウンで1番目のものにdepeningが間違っていました。 – n3wjack

0

それはリストをリフレッシュだとき、あなたはどんなペットを選択されていないためです。デフォルトでは最初のものが表示されますが、彼が選択されているわけではありません。

あなたが実際にリストの最初の1つを選択する命令を追加することができます。ここ

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

は異なるアプローチです。ペット所有者はオブジェクトの配列になります。オプションのバインディングを使用します。ここはフィドルです。

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> 
関連する問題