Bootstrap-multiselect: KnockoutJS se liant à la valeur de l'objet (pas une simple valeur) ... Correctif de piratage inclus

Créé le 2 mai 2015  ·  3Commentaires  ·  Source: davidstutz/bootstrap-multiselect

J'utilise la liaison de sélection knockout où un objet entier est lié comme valeur... pas seulement une chaîne.

bootstrap-multiselect n'a pas aimé cela car il utilise la "valeur" pour relier ses éléments de liste déroulante à l'option de sélection correspondante. Pour ce faire, vous devez avoir défini l'attribut "optionsValue" dans votre liaison knockout afin que l'option ait un attribut "value". Cependant, la définition de l'attribut "optionsValue" a alors le résultat attendu de définir uniquement cette valeur dans mon selectedOptions observableArray ... pas l'objet entier.

Il est tout à fait possible que je sois la seule personne à utiliser la fonctionnalité de knockout qui vous permet de lier les options à des objets entiers, mais juste au cas où je ne le serais pas... voici le correctif :

Création de deux nouvelles options bootstrap-multiselect appelées "optionsKey" et "observableKey" afin qu'il sache où aller pour une valeur à laquelle il peut se rapporter :

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

Dans mon modèle de vue knockout, j'ai défini l'attribut référencé par "optionsKey" sur chaque option :

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

Maintenant, je plonge dans le fichier bootstrap-multiselect.js. La première chose que je devais faire ici est en haut où il ajoute le gestionnaire d'init 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 });
        }
    }
    ...

Ensuite, j'ai dû modifier la fonction createOptionValue dans bootstrap-multiselect.js pour utiliser d'abord cette clé comme valeur qu'elle définit dans ses éléments de liste :

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

    ...
}

Enfin, j'ai dû modifier la fonction getOptionByValue dans bootstrap-multiselect.js pour trouver des éléments d'option basés sur cet attribut au lieu de la valeur :

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

Tous les 3 commentaires

Merci, inclura ceci dans la FAQ! Je suis sûr que cela est également utile pour les autres utilisateurs.

Merci pour cette astuce - j'essayais également d'effectuer une liaison pour sélectionner des objets et cette rédaction a été très utile. La seule chose que je devais faire en plus du code de @APM3 est également de remplir l'attribut "value" de mes options dans la fonction SetOptionKey :

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

Merci encore pour cette rédaction.

Voir l' essentiel pour la liaison knockout cet objet pris en charge. Remplacez simplement la liaison réelle du fichier bootstrap-multiselect.js. Dans ce code, vous n'avez pas besoin de mettre dans votre machine virtuelle pour définir l'option.

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

J'ai ajouté un prétraitement aux liaisons pour ajouter implicitement optionsAfterRender .

Cette page vous a été utile?
0 / 5 - 0 notes