Bootstrap-multiselect: Привязка KnockoutJS к значению объекта (не простому значению) ... Включено исправление взлома

Созданный на 2 мая 2015  ·  3Комментарии  ·  Источник: davidstutz/bootstrap-multiselect

Я использую привязку выбора с выбиванием, где весь объект привязан как значение ... а не только строка.

bootstrap-multiselect это не понравилось, потому что он использует «значение», чтобы связать элементы своего раскрывающегося списка с соответствующей опцией выбора. Для этого вы должны установить атрибут «optionsValue» в привязке нокаута, чтобы параметр имел атрибут «значение». Однако установка атрибута optionsValue тогда дает ожидаемый результат установки только этого значения в моем selectedOptions observableArray ... а не всего объекта.

Вполне возможно, что я единственный человек, который использует функциональность knockout, которая позволяет вам привязывать параметры ко всем объектам, но на всякий случай я нет ... вот исправление взлома:

Созданы две новые опции 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: 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 });
        }
    }
    ...

Затем мне пришлось изменить функцию createOptionValue в bootstrap-multiselect.js, чтобы сначала использовать этот ключ в качестве значения, которое он устанавливает в своих элементах списка:

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;
        }
    }

    ...
}

Наконец, мне пришлось изменить функцию getOptionByValue в bootstrap-multiselect.js, чтобы найти элементы параметров на основе этого атрибута вместо значения:

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 Комментарий

Спасибо, включу в FAQ! Я уверен, что это полезно и для других пользователей.

Спасибо за этот совет - я также пытался выполнить привязку для выбора объектов, и эта запись была очень полезной. Единственное, что мне нужно было сделать в дополнение к коду @ APM3 , это также заполнить атрибут «значение» моих параметров в функции SetOptionKey:

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. В этом коде вам не нужно вводить параметр в виртуальную машину.

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

Я добавил препроцессор в привязки, чтобы неявно добавить optionsAfterRender .

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

rodrigonunes100 picture rodrigonunes100  ·  3Комментарии

Calaelen picture Calaelen  ·  9Комментарии

sourav-prescriber-360 picture sourav-prescriber-360  ·  8Комментарии

Furgas picture Furgas  ·  8Комментарии

zeyabadar picture zeyabadar  ·  5Комментарии