1

バインディングを使用して複雑な JavaScript オブジェクトのリストにバインドされたselect要素があります。options

<select data-bind="options: availableCountries, optionsText: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'"></select>

ここで、availableCountries は JavaScript オブジェクトの監視可能な配列です。このフィドルで完全な例を見ることができます。

これで、リスト内の項目を選択するとうまくいきます。ただし、アプリケーションの他の部分から値を更新する必要がある場合は、availableCountries 配列にあるものとまったく同じ Country オブジェクトを使用する場合にのみ更新できます。これはこの関連する質問でも確立されていますが、残念ながら私の問題は解決しません。

options bindingのドキュメントでは、彼らはこの問題を予期しており、optionsValueバインディングを使用する必要があると述べています。

通常、使用可能なオプションのセットを更新するときに、KO が選択を正しく保持できるようにする方法としてのみ、optionsValue を使用する必要があります。たとえば、Ajax 呼び出しを介して「車」オブジェクトのリストを繰り返し取得し、選択した車を確実に保持したい場合は、optionsValue を「carId」または各「車」オブジェクトが持つ一意の識別子に設定する必要がある場合があります。そうしないと、KO は以前の「車」オブジェクトのどれが新しいオブジェクトのどれに対応するかを必ずしも認識できません。

しかし、これは値のバインディングにも影響するため、残念ながら機能しません。 に設定optionsValueすると'countryName'selectedCountryオブジェクト全体ではなく国の名前のみが含まれます。

これらを組み合わせる方法を探しています。値をオブジェクト全体にしたいのですが、オプション値の比較では、指定した特定のプロパティを使用する必要があります。基本的に、次の行の何か:

<select data-bind="options: availableCountries, optionsText: 'countryName', optionsComparator: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'"></select>

ただし、私が見る限り、これにはvalueバインディングの変更が含まれます。他に選択肢はありますか?これを他の方法で解決できますか?エクステンダー?カスタムバインディングハンドラ?

4

2 に答える 2

3

この問題を修正するバインディングを選択しました。バインディングのコレクションを確認してください

デモ、ドロップダウンはページの最後にあります http://jsfiddle.net/H8xWY/8/

https://github.com/AndersMalmgren/Knockout.Bindings

コード

ko.bindingHandlers.selected = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var selected = valueAccessor();
        var items = ko.utils.unwrapObservable(allBindingsAccessor().options);
        var key = allBindingsAccessor().optionsKey ? allBindingsAccessor().optionsKey : allBindingsAccessor().optionsText;

        var observable = ko.computed({
            read: function () {
                var value = ko.utils.unwrapObservable(selected);
                return ko.utils.arrayFirst(items, function (item) {
                    return value != null ? ko.utils.unwrapObservable(item[key]) == ko.utils.unwrapObservable(value[key]) : false;
                });
            },
            write: function (value) {
                writeValueToProperty(selected, allBindingsAccessor, "selected", value);
            }
        });

        ko.applyBindingsToNode(element, { value: observable });
    }
};
于 2013-01-21T21:52:29.033 に答える
1

getCountryByPop メソッドを availableCountries 配列にアタッチし、それを呼び出してオブザーバブルの値を設定することで、同様の問題を解決しました。

availableCountries.getCountryByPop = function(pop) {
    var ret;
    this().forEach(function(country) {
        if (country.countryPopulation == pop) {
            ret = country;
        }
    });
    return ret;
};

...

viewModel.selectedCountry(availableCountries.getCountryByPop(9));

jsfiddle.net/6BaP5/

于 2014-07-18T18:22:49.410 に答える