Bootstrap-multiselect: KnockoutJS 绑定到对象值(不是一个简单的值)......包括黑客修复

创建于 2015-05-02  ·  3评论  ·  资料来源: davidstutz/bootstrap-multiselect

我正在使用淘汰赛选择绑定,其中将整个对象绑定为值......而不仅仅是一个字符串。

bootstrap-multiselect 不喜欢这样,因为它使用“值”将其下拉列表项关联回相应的选择选项。 为了做到这一点,您必须在淘汰赛绑定中设置“optionsValue”属性,以便该选项具有“value”属性。 但是,设置“optionsValue”属性然后具有仅在我的 selectedOptions observableArray 中设置该值的预期结果......而不是整个对象。

很有可能我是唯一一个在淘汰赛中使用功能的人,该功能可让您将选项绑定到整个对象,但以防万一我不是......这是黑客修复:

创建了两个新的 bootstrap-multiselect 选项,称为“optionsKey”和“observableKey”,以便它知道去哪里寻找与它相关的值:

<select id="mySelect" data-bind="options: myOptions, selectedOptions: mySelectedOptions, optionsText: 'myDisplayText', optionsAfterRender: SetOptionKey, multiselect: { optionsKey: 'data-key', observableKey: 'Key' }" multiple="multiple"></select>

在我的淘汰赛视图模型中,我在每个选项上设置了“optionsKey”引用的属性:

myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

现在我深入研究 bootstrap-multiselect.js 文件。 我必须在这里做的第一件事是在顶部添加淘汰赛 init 处理程序。

init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    ...
    if (allBindings.has('selectedOptions')) {
        var selectedOptions = allBindings.get('selectedOptions');
        if (ko.isObservable(selectedOptions)) {
            ko.computed({
                read: function () {
                    selectedOptions();

                    // Added to handle knockout binding to an object...not just a value
                    // multiselect needs the selected property on the options, else it wont show them on refresh
                    if ((config.optionsKey !== undefined) &&
                        (config.optionsKey !== null) &&
                        (config.optionsKey.length > 0) &&
                        (config.observableKey !== undefined) &&
                        (config.observableKey !== null) &&
                        (config.observableKey.length > 0)) {
                        var _optionsKey = config.optionsKey;
                        var _observableKey = config.observableKey;
                        ko.utils.arrayForEach(selectedOptions(), function (selectedOption) {
                            $("option[" + _optionsKey + "='" + selectedOption[_observableKey]() + "']", $element).prop('selected', true);
                        })
                    }

                    setTimeout(function () {
                        $element.multiselect('refresh');
                    }, 1);
                },
                disposeWhenNodeIsRemoved: element
            }).extend({ rateLimit: 100, notifyWhenChangesStop: true });
        }
    }
    ...

接下来,我必须修改 bootstrap-multiselect.js 中的 createOptionValue 函数,以首先使用此键作为它在其列表项中设置的值:

createOptionValue: function (element) {
    ...

    var value = $element.val();
    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var key = $element.attr(this.options.optionsKey);
        if ((key !== undefined) && (key !== null) && (key.length > 0)) {
            value = key;
        }
    }

    ...
}

最后,我不得不修改 bootstrap-multiselect.js 中的 getOptionByValue 函数,以根据此属性而不是值查找选项元素:

getOptionByValue: function (value) {
    var valueToCompare = value.toString();

    // Added to handle knockout binding to an object...not just a value
    if ((this.options.optionsKey !== undefined) && (this.options.optionsKey !== null) && (this.options.optionsKey.length > 0)) {
        var opt = $("option[" + this.options.optionsKey + "='" + valueToCompare + "']", this.$select).first();
        if( (opt !== undefined) && (opt !== null) ) {
            return $(opt);
        }
    }

    var options = $('option', this.$select);

    for (var i = 0; i < options.length; i = i + 1) {
        var option = options[i];
        if (option.value === valueToCompare) {
            return $(option);
        }
    }
},
question

所有3条评论

谢谢,将在常见问题解答中包含此内容! 我相信这对其他用户也有帮助。

谢谢你的提示 - 我也试图完成对选择对象的绑定,这篇文章非常有帮助。 除了@APM3的代码之外,我唯一要做的就是在 SetOptionKey 函数中填充我的选项的“value”属性:

self.SetOptionKey = function (option, item) { ko.applyBindingsToNode(option, { attr: { "data-key": item.Value } }, item); ko.applyBindingsToNode(option, { attr: { "value": item.Value } }, item); }

再次感谢您写这篇文章。

有关支持对象的淘汰赛绑定,请参阅要点。 只需替换 bootstrap-multiselect.js 文件中的实际绑定即可。 在此代码中,您不需要放入 vm 来设置选项。

//Just like this one
myVM.SetOptionKey = function ( option, item ) {
    ko.applyBindingsToNode( option, { attr: { "data-key": item.Key } }, item );
};

我向绑定添加了预处理以隐式添加optionsAfterRender

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

Calaelen picture Calaelen  ·  9评论

andriijas picture andriijas  ·  8评论

Jojoshua picture Jojoshua  ·  8评论

Furgas picture Furgas  ·  8评论

petukhov-ds picture petukhov-ds  ·  6评论