1

v3.5.x からのアップグレードに関して、select2 v4.0 を評価しています。これをノックアウト v3.5.2 で使用しています。私たちのシナリオは、ユーザーが ajax 呼び出しからの js オブジェクトに基づいて複数のオプションを選択できるようにすることです。selectedoptions バインディングは、id のリストだけでなく、バ​​インドされた observablearray に js オブジェクト全体を格納する必要があります。

私のテストでは、ここに私が発見したものがあります

これは、事前定義されたオプションのリストを持つ select2 です。各オプションには、id、text、および displayText プロパティがあります。その結果、multipleSelectedObjects オブザーバブル配列が js オブジェクト全体の配列を持つことになります。これは、optionsValue 引数を設定しなかったという事実に基づいて期待するものです。

<select class="multipleSelect" data-bind="options: multipleOptions, selectedOptions: multipleSelectedObjects, optionsText: 'displayText', select2v4: multipleOptionsSetup" style="width: 200px">

これは、事前定義されたオプションのリストを持つ select2 です。各オプションには、id、text、および displayText プロパティがあります。その結果、multipleSelectedValue オブザーバブル配列は、選択された js オブジェクトの ID を表す int の配列を持つことになります。これは、optionsValue 引数を設定したという事実に基づいて期待されるものです。

<select class="multipleSelect3" data-bind="options: multipleOptions, selectedOptions: multipleSelectedValue, optionsText: 'text', optionsValue: 'id', select2v4: multipleOptionsSetup" style="width: 200px">

これは、ajax オプションを使用してサービス呼び出しを行い、オプションを返す select2 です。返される各オプションには、id、text、および displayText プロパティがあります。その結果、選択された js オブジェクトの ID を表す int の配列が selectedItems オブザーバブル配列に含まれることになります。これは私が期待するものではありません。上記の最初のselect2で行ったように、optionsTextプロパティだけを設定しようとしましたが、違いはありませんでした

<select id="select2Input" data-bind="selectedOptions: selectedItems, select2v4: selectSetup" style="width: 400px">

これはselect2の問題かもしれないと思いますが、よくわかりません。select2v4 バインディング ハンドラを以下に示します。ノックアウトが selectedOptions セクションにヒットした最後のシナリオでは、値は文字列であり、ajax を使用するときに select2 がオブジェクト全体を渡すように設定されていないと思わせます。他の誰かがこれを経験していますか?これはバグですか、それとも仕様ですか?

// NOTE: this binding handler is made for select2 version 4.0

 ko.bindingHandlers.select2v4 = { 

     init: function (element, valueAccessor, allBindingsAccessor) { 

         var bindingValue = ko.unwrap(valueAccessor()); 

         var allBindings = allBindingsAccessor(); 

         var valueDataChange; 

         // Observe external data changes; set data on change 

         if (ko.isObservable(allBindings.valueData)) { // special data binding 

             var onChange = false; 

             allBindings.valueData.subscribe(function (value) { // subscribe to external data changes 
                 if (onChange) return; // ignore if on change to prevent recursion 
                 $(element).select2("data", value, false); // set data explicitly; do not trigger change }); 

             if (ko.isWritableObservable(allBindings.valueData)) { 

                 valueDataChange = function () { 

                     onChange = true; // suppress valueData subscription 

                     allBindings.valueData($(element).select2("data")); 

                     onChange = false; 

                 }; 

                 $(element).on("change", valueDataChange); // update observable on data change 

             } 

         } 

         // Observe external value changes 

         else if (ko.isObservable(allBindings.value)) { // input or single select with observable value binding 

             allBindings.value.subscribe(function (value) { // subscribe to external value changes 

                 if (typeof value === "string") { // optionsValue or tags specified 

                     if (bindingValue.tags) { // tags specified 

                         value = value.split(bindingValue.separator || ','); // split on value separator 

                     } 

                     $(element).val(value); // set val to allow select2 to resolve data from values; do not trigger change 

                 } 
                 else { // optionsValue not specified, value is complex data 

                     $(element).select2("data", value, false); // set data explicitly; do not trigger change 

                 } 

             }); 

         } 

 // Observe external selection changes 

         else if (ko.isObservable(allBindings.selectedOptions)) { // multiselect with observable selection binding 

             allBindings.selectedOptions.subscribe(function (value) { // subscribe to external selection changes 

                 if (value.length > 0 && typeof value[0] === "string") { // optionsValue specified 

                     $(element).val(value); // set val to allow select2 to resolve data from values; do not trigger change 

                 } 
                 else { // optionsValue not specified, value is complex data 

                     $(element).select2("data", value, false); // set data explicitly (only works if complex data object has 'id' property); do not trigger change 

                 } 

             }); 

         } 

         // Destroy select2 on element disposal 

         ko.utils.domNodeDisposal.addDisposeCallback(element, function () { 

             $(element).select2('destroy'); 

             if (valueDataChange != null) { 

                 $(element).off("change", valueDataChange); 

             } 

         }); 

         // Apply select2 and initialize data; delay to allow other binding handlers to run 

         setTimeout(function () { 

             // Apply select2 

             $(element).select2(bindingValue); 

             // Initialize data 

             if ("valueData" in allBindings) { 

                 $(element).select2("data", ko.unwrap(allBindings.valueData), false); 

             } 

         }, 0); 

      } 

  };
4

2 に答える 2

1

以前のバージョンと比較して、select2 v4 が内部でどのように機能するかについて、多くの大きな変更がありました。それらの 1 つは、データをロードするために ajax を使用する場合 (別名タイプアヘッド)、select2 が選択されたオブジェクトを格納する方法です。私の同僚は、その場合、選択されたオブジェクトが読み取り専用コレクションに保存され、変更が行われたときに適切に通知されず、通常のバインドが期待どおりに機能しないことを理解できました。発見したように、selectedOptions へのバインディングはオブジェクトのリストではなく、ID のリストになります。彼は、以下に示す select2 のバインディング ハンドラーを思いつきました。これは、通常の選択スタイルのバインディングを処理し、selectData という新しいバインディングを追加します。このバインディングは、ajax でリモート データ ロードを使用している場合に、選択されたオブジェクトのリストを取得します。

<select id="select2Input" data-bind="select2Data: selectedItems, select2: selectSetup" style="width: 400px"></select>

https://github.com/shaftware/knockout-select2

于 2015-07-06T13:23:34.117 に答える