Bootstrap-multiselect: オブジェクト値(単純な値ではない)へのKnockoutJSバインディング...ハック修正が含まれています

作成日 2015年05月02日  ·  3コメント  ·  ソース: davidstutz/bootstrap-multiselect

文字列だけでなく、オブジェクト全体が値としてバインドされるノックアウト選択バインディングを使用しています。

bootstrap-multiselectは、「値」を使用してドロップダウンリストアイテムを対応する選択オプションに関連付けるため、これを好みませんでした。 これを行うには、オプションが「value」属性を持つように、ノックアウトバインディングで「optionsValue」属性を設定する必要があります。 ただし、「optionsValue」属性を設定すると、オブジェクト全体ではなく、selectedOptionsobservableArrayにその値のみを設定するという期待される結果が得られます。

オプションをオブジェクト全体にバインドできるノックアウト内の機能を使用しているのは私だけである可能性は十分にありますが、そうでない場合に備えて...ハックの修正は次のとおりです。

「optionsKey」および「observableKey」と呼ばれる2つの新しいブートストラップ-複数選択オプションを作成しました。これにより、関連する値をどこに配置するかがわかります。

<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件

ありがとう、FAQにこれを含めます! これは他のユーザーにも役立つと確信しています。

このヒントをありがとう-私は選択したオブジェクトへのバインディングも達成しようとしていましたが、この記事は非常に役に立ちました。 @ 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 評価