2

これは機能しません (カスタム バインディングが呼び出されますが、ドロップダウンは空です)

<select id="parentArea" class="chosen-select" data-bind="
   chosen:{},
   options: parentAreas,
   optionsCaption: 'Choose...',
   optionsText: 'Label',
   value: selectedParentArea">
</select>

しかし、これは機能します(ドロップダウンが入力されています)

<select id="parentArea" class="chosen-select" data-bind="
   options: parentAreas,
   optionsCaption: 'Choose...',
   optionsText: 'Label',
   value: selectedParentArea">
</select>

ドロップダウンにカスタム バインディングを追加したいのですが、その方法がわかりません。

カスタムバインディングはシンプルです

ko.bindingHandlers.chosen = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        console.log('chosen', element);
        $(element).chosen({});
    }
};

アップデート

.chosen({});

別の Javascript (harvesthq.github.io/chosen) のメソッドです。

コメントアウトすると、残りのバインド作業が発生することに気付きました。本当に必要なのは、「$(element).chosen ({});」を実行することです。他のすべてのバインディングが終了した後。

更新 2

すべてのバインディングが適用された後に「chosen」を手動で適用すると、うまく機能します。たとえば、このJSを実行するボタンを使用できます

 function run() {
    $('.chosen-select').chosen({});
};    

すべてのバインディングが完了したら、自動的に行う必要があります (コールバック関数?)。どうやったらよいかわかりません。

更新 3

「parentAreas」は静的配列ではありません。Web サービスからロードされます。

function ViewModel() {

    var self = this;

   self.init = function () {

        //load parent areas from web service
    };

    self.init(); //Running the init code
}

ko.applyBindings( new ViewModel());

親領域の準備ができたら、「選択された」ボックスのカスタム バインディングを初期化したいと考えています。

更新 4

新しいバージョン (動作しますが、バインディングがハードコードされているため再利用できません)

ko.bindingHandlers.chosen = { init: 関数 (要素、valueAccessor、allBindingsAccessor、viewModel、コンテキスト) {

        viewModel.parentAreas.subscribe(function(newParentAreas) {
            if (newParentAreas && newParentAreas.length > 0) {

                ko.applyBindingsToNode(element, {
                    options: viewModel.parentAreas,
                    optionsCaption: 'Choose...',
                    optionsText: 'Label',
                    value: viewModel.selectedParentArea
                });
                $(element).chosen({});
            }
        });
    }
};

// そしてバインディングはただの data-bind="chosen:{}

更新 5 複数の初期化を回避する (ハッキーな方法)

ko.bindingHandlers.parentAreaComboBox = {

    initialised: false,
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {

        viewModel.parentAreas.subscribe(function (newParentAreas) {

            if (newParentAreas && newParentAreas.length > 0) {

                if (ko.bindingHandlers.parentAreaComboBox.initialised) {
                    return;
                }
                ko.applyBindingsToNode(element, {
                    options: viewModel.parentAreas,
                    optionsCaption: 'Choose...',
                    optionsText: 'Label',
                    value: viewModel.selectedParentArea
                });
                $(element).chosen({});
                ko.bindingHandlers.parentAreaComboBox.initialised = true;
            }
        });
    }
};

更新 6

私は一般的な解決策を書きました(以下の私の答えを見てください)

4

4 に答える 4

5

バインディングの順序に依存するのはアンチパターンです。

それ自体の前に他のバインディングを実行する必要があるカスタム バインディングがある場合は、次のようにカスタム バインディングからそれらのバインディングを呼び出す必要があります。

ko.applyBindingsToNode(element, { options: arr, value: val });

そしてその後$(element).chosen

于 2013-10-31T13:16:02.383 に答える
1

あなたの問題はchosenプラグイン自体にあると思います。タグに適用すると、マークアップが変更されます (通常の html ではなくなります.chosen) 。 したがって、バインディングでは、最初にカスタム バインディングを適用してから、html マークアップを変更するため、バインディングが適切に機能しません。selectselect
chosen

その問題を解決するには、カスタムバインディングを最初ではなく最後に適用する必要があります.. koバインディングが通常どおり適用され、カスタムバインディングが適用され、selectが変更されるようにします(ただし、selectを適切に構築しました)

アップデート

option要素が生成された後に関数を実行するには、コールバックを使用できます..こちらoptionsAfterRenderのドキュメントをご覧ください

別の汚い解決策は、使用することですsettimeout

于 2013-10-31T11:50:29.670 に答える