1

我有一个select使用绑定绑定到复杂 javascript 对象列表的元素options

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

其中 availableCountries 是一个可观察的 javascript 对象数组。你可以在这个 fiddle中看到完整的例子。

现在,当我在列表中选择一个项目时,这可以正常工作。但是,如果我需要从应用程序的其他部分更新值,则只有在使用与 availableCountries 数组中完全相同的 Country 对象时才能执行此操作。这也已在这个相关问题中建立,但不幸的是它并没有解决我的问题。

options binding的文档中,他们预料到了这个问题,并说我应该使用optionsValue绑定:

通常,您只想使用 optionsValue 来确保 KO 在更新可用选项集时可以正确保留选择。例如,如果您通过 Ajax 调用反复获取“汽车”对象列表并希望确保保留所选汽车,您可能需要将 optionsValue 设置为“carId”或每个“汽车”对象具有的任何唯一标识符, 否则 KO 不一定知道之前的“汽车”对象中的哪些对应于新对象中的哪些。

但不幸的是,这不起作用,因为它也会影响值绑定 - 如果我设置optionsValue'countryName'selectedCountry将只包含国家/地区的名称而不是整个对象。

我正在寻找一种方法来结合这些。我仍然希望 value 是整个对象,但我希望选项值比较使用我指定的特定属性。基本上,是这样的:

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

但是,据我所知,这涉及修改value绑定。我还有其他选择吗?我可以用其他方式解决这个问题吗?扩展器?自定义绑定处理程序?

4

2 回答 2

3

我已经制作了一个修复此问题的选定绑定,请检查我的绑定集合

Demo,下拉菜单在页面末尾 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 数组,然后调用它来设置 observable 的值,解决了类似的问题:

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 回答