Bootstrap-multiselect: Enlace de KnockoutJS al valor del objeto (no es un valor simple) ... Corrección de pirateo incluido

Creado en 2 may. 2015  ·  3Comentarios  ·  Fuente: davidstutz/bootstrap-multiselect

Estoy usando el enlace de selección knockout donde un objeto completo está vinculado como valor ... no solo una cadena.

A bootstrap-multiselect no le gustó esto porque usa el "valor" para relacionar los elementos de su lista desplegable con la opción de selección correspondiente. Para que pueda hacer esto, debe haber establecido el atributo "optionsValue" en su enlace de eliminación para que la opción tenga un atributo "value". Sin embargo, establecer el atributo "optionsValue" tiene el resultado esperado de establecer solo ese valor en mi selectedOptions observableArray ... no todo el objeto.

Es muy posible que yo sea la única persona que usa la funcionalidad dentro del knockout que le permite vincular las opciones a objetos completos, pero en caso de que no lo sea ... aquí está la solución del truco:

Creó dos nuevas opciones de bootstrap-multiselect llamadas "optionsKey" y "observableKey" para que sepa a dónde ir para obtener un valor con el que pueda relacionarse:

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

En mi modelo de vista eliminatoria, configuro el atributo al que hace referencia "optionsKey" en cada opción:

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

Ahora me sumerjo en el archivo bootstrap-multiselect.js. Lo primero que tuve que hacer aquí es en la parte superior donde está agregando el controlador de inicio knockout.

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

Luego tuve que modificar la función createOptionValue en bootstrap-multiselect.js para usar primero esta clave como el valor que establece en sus elementos de lista:

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

    ...
}

Por último, tuve que modificar la función getOptionByValue en bootstrap-multiselect.js para encontrar elementos de opción basados ​​en este atributo en lugar de valor:

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

Todos 3 comentarios

¡Gracias, incluiremos esto en las preguntas frecuentes! Estoy seguro de que esto también es útil para otros usuarios.

Gracias por este consejo: también estaba tratando de lograr la vinculación para seleccionar objetos y esta redacción fue muy útil. Lo único que tuve que hacer además del código de @ APM3 es también completar el atributo "valor" de mis opciones en la función SetOptionKey:

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

Gracias de nuevo por este artículo.

Consulte la esencia para obtener información sobre la unión de nocaut de ese objeto admitido. Simplemente reemplace el enlace real del archivo bootstrap-multiselect.js. En este código, no es necesario que lo pongas en tu vm para configurar la opción.

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

Agregué un optionsAfterRender .

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

donbonifacio picture donbonifacio  ·  7Comentarios

Jojoshua picture Jojoshua  ·  8Comentarios

psyclight picture psyclight  ·  4Comentarios

zephyx picture zephyx  ·  7Comentarios

andriijas picture andriijas  ·  8Comentarios