Knockout with Chosen 不设置初始选择的选项

Knockout with Chosen doesn't set the initial selected options

我在使用 Chosen 和 Knockout 3.3.0 设置最初选择的选项时遇到问题。

我已经实现了来自 this question 的自定义 Chosen 绑定,它非常适合选择元素:

ko.bindingHandlers.chosen = {
    init: function (element) {
        ko.bindingHandlers.options.init(element);
        $(element).chosen({ disable_search_threshold: 10 });
    },
    update: function (element, valueAccessor, allBindings) {
        ko.bindingHandlers.options.update(element, valueAccessor, allBindings);
        $(element).trigger('chosen:updated');
    }
};

问题是,如果我设置一个初始值,它不会显示为选中:

<select multiple class="chosen-select" data-bind="chosen: options,
                                        optionsText: 'Label',
                                        optionsValue: 'Id',
                                        selectedOptions: selected">
</select>

如果我使用常规选项绑定,它会正常工作:

<select multiple data-bind="options: options,
                                        optionsText: 'Label',
                                        optionsValue: 'Id',
                                        selectedOptions: selected">
</select>

我将两者都实现为 jsFiddle。如果您更改 self.selected observableArray(),然后更改 运行,您可以看到它反映在第二个 <select> 中,但在第一个中什么也没有显示。

诀窍是在绑定发生后评估所选内容,因为如果 <options> 不在 DOM 中,所选内容将无法正确初始化。

使用 setTimeout 有点难看,但它有效,因为它会延迟重新初始化,直到绑定完成。

编辑: 使用订阅来处理对所选选项的更改。我发现这比接受的答案更独立。

** FIDDLE: **

https://jsfiddle.net/brettwgreen/xp1b7cff/

JS:

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindings) {
        ko.bindingHandlers.options.init(element, valueAccessor, allBindings);
        var options = ko.unwrap(valueAccessor);
        var el = $(element);
        el.chosen();
        var selectedOptions = allBindings.get('selectedOptions');
        if (ko.isObservable(selectedOptions)) {
            selectedOptions.subscribe(function () {
                setTimeout(function () {
                    el.trigger('chosen:updated');
                }, 10);
            }, null, 'change');
        }
    },
    update: function (element, valueAccessor, allBindings) {
        ko.bindingHandlers.options.update(element, valueAccessor, allBindings);
    }
};

    function viewModel() {

        var self = this;

        self.options = ko.observableArray([{ Id: 1, Label: 'Administrator' }, { Id: 2, Label: 'Moderator' }]);

        self.selected = ko.observableArray([2]);

    }
    ko.applyBindings(new viewModel());

如果 select 处于多选模式,您还必须设置 selectedOptions 绑定才能与 chosen 一起正常工作。

问题是,当您的 selected 可观察数组更改时,selectedOptions 正确地设置了 DOM 中的选定选项,但不会触发 'chosen:updated' 事件,因此chosen 多选未更新。

一个解决方案是创建一个新的 chosenSelectedOptions 委托给原始处理程序并触发 update:

中的事件
ko.bindingHandlers.chosenSelectedOptions = {
            init: function (element, valueAccessor) {
                ko.bindingHandlers.selectedOptions.init(element, valueAccessor);
            },
            update: function (element, valueAccessor, allBindings) {
                ko.bindingHandlers.selectedOptions.update(element, valueAccessor, allBindings);
                $(element).trigger('chosen:updated');
            }
        };

并在您的绑定中使用它:

<select multiple class="chosen-select" data-bind="chosen: options,
                                            optionsText: 'Label',
                                            optionsValue: 'Id',
                                            chosenSelectedOptions: selected"></select>

演示 JSFiddle.