Select2使用ajax,多个和敲除绑定不保存对象到selectedOptions



我正在评估select2 v4.0与我们从v3.5.x升级的关系。我们将其用于淘汰v3.5.2。我们的场景是,我们希望允许用户根据来自ajax调用的js对象选择多个选项。selectedoptions绑定应该将整个js对象存储在其绑定到的observalearray中,而不仅仅是id列表。

在我的测试中,以下是我发现的

这是一个带有预定义选项列表的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可观察数组最终具有一个int数组,该数组表示所选js对象的id,这是我基于设置optionsValue参数的事实所期望的

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

这是一个select2,它使用ajax选项进行服务调用以返回选项。返回的每个选项都有一个id、text和displayText属性。结果是selectedItems可观察数组最终具有一个int数组,该数组表示所选js对象的id。这不是我所期望的。我试着像上面第一个select2一样只设置optionsText属性,但这并没有改变

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

我认为这可能是一个选择性的问题,但我不确定。我们的select2v4绑定处理程序如下所示。在最后一个场景中,当knockout命中selectedOptions部分时,该值是一个字符串,这让我认为select2在使用ajax时没有设置为传递整个对象。有其他人经历过这种情况吗?这是个bug还是故意的?

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

与以前的版本相比,select2 v4的内部工作方式发生了许多重大变化。其中之一是select2在使用ajax加载数据(也称为typeahead)的情况下如何存储所选对象。我的一位同事发现,在这种情况下,所选对象存储在只读集合中,并且在进行更改时不会正确通知,加上正常绑定无法按预期工作。正如我们所发现的,绑定到selectedOptions并没有生成对象列表,而是生成id列表。他为select2提出了如下所示的绑定处理程序,它将处理常规的select风格绑定,并添加一个名为selectData的新绑定,如果您使用ajax进行远程数据加载,它将为您提供一个选定对象的列表。如果您使用ajax加载数据,并且希望获得所选对象的列表而不是id,则只需要selectData绑定,否则您可以绑定到value或selectedOptions,并且设置类型将按预期工作。

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

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

嗨,您是否尝试使用optionsAfterRender来设置值?

这对我有效:

<select id="selectArticles" multiple
 data-bind="options: availableArticles, selectedOptions: selectedArticles,
 optionsText: function(item){return item.title},
 optionsAfterRender: function(option, item){option.value = item}">
</select>

工作小提琴

最新更新