Select2淘汰nulti选择设置值问题

问题描述

所以我有许多使用淘汰赛绑定的select2下拉列表。 最初,它似乎工作正常。当用户进行选择(多选)时。模型已更新,生活很美好。 当您具有要显示为选定模型的值时,就会出现我的问题。 例如在编辑内容时。您使用预先填充的值加载表单。

这是我的绑定处理程序

ko.bindingHandlers.select2 = {
    init: function (el,valueAccessor,allBindingsAccessor) {
        ko.utils.domNodedisposal.adddisposeCallback(el,function () {
                $(el).select2('destroy');
            });

        var allBindings = allBindingsAccessor(),select2 = ko.utils.unwrapObservable(allBindings.select2);

        $(el).select2(select2);
    },update: function (el,allBindingsAccessor) {
        var allBindings = allBindingsAccessor();

        if ("value" in allBindings) {
            if ((allBindings.select2.multiple || el.multiple) && allBindings.value().constructor !== Array) {
                $(el).val(allBindings.value().split(',')).trigger('change');
            } else {
                $(el).val(allBindings.value()).trigger('change');
            }
        } else if ("selectedOptions" in allBindings) {
            var converted = [];
            var textAccessor = function (value) { return value; };
            if ("optionsText" in allBindings) {
                textAccessor = function (value) {
                    var valueAccessor = function (item) { return item; }
                    if ("optionsValue" in allBindings) {
                        valueAccessor = function (item) { return item[allBindings.optionsValue]; }
                    }
                    var items = $.grep(allBindings.options(),function (e) { return valueAccessor(e) === value });
                    if (items.length === 0 || items.length > 1) {
                        return "UNKNowN";
                    }
                    return items[0][allBindings.optionsText];
                }
            }
            $.each(allBindings.selectedOptions(),function (key,value) {
                    converted.push({ id: value,text: textAccessor(value) });
                });
            $(el).select2("data",converted);
        }
        $(el).trigger("change");
    }
};

selected选项绑定到Guid列表。这是javascript端的字符串列表。 我相信Select2 select需要字符串才能设置选定的值。

我的选择看起来很像:

<select class="form-control input-sm multi-select" data-bind="selectedOptions: BrandIds,options: Brands,valueAllowUnset: true,optionsText:'Description',optionsValue: 'Value',select2:{ placeholder: 'Please Select...',allowClear: true,multiple:'multiple'},css: { 'jackpot-input-error': BrandIds.error() && BrandIds.isModified() }" multiple></select>

所以我发现正在发生的事情是从BrandIds中从服务器重新运行的初始值被删除了。我在BrandIds的订阅中确定这一点。订阅函数的参数如下所示

[
{
    "status": "deleted","value": "cd1f6c04-b7ae-479e-b722-65f837e65ec2","index": 0
},{
    "status": "deleted","value": "bd66ebe1-080b-4455-9094-bf0464d4adbf","index": 1
}

]

解决方法

我已经删除了绑定处理程序的整个update部分,这似乎毫无意义。淘汰赛将处理optionsTextoptionsValue绑定。

Knockout操作原始的<select>元素,该元素隐藏在后台,并且select2注意到这些操作并相应地更新其小部件。似乎确实不需要干预。

请注意如何从视图模型的初始状态中预先选择以下示例中的两个选项。当您通过自己的函数更改BrandIds可观察数组中的项目时,例如在Ajax请求之后,应该会发生同样的事情。

ko.bindingHandlers.select2 = {
    init: function (el,valueAccessor,allBindings) {
        var options = ko.unwrap(valueAccessor());

        $(el).select2(options);
        ko.utils.domNodeDisposal.addDisposeCallback(el,function () {
            $(el).select2('destroy');
        });
    }
};

var vm = {
  BrandIds: ko.observableArray(["ID_A","ID_C"]),Brands: ko.observableArray([
    {Description: 'Brand A',Value: "ID_A"},{Description: 'Brand B',Value: "ID_B"},{Description: 'Brand C',Value: "ID_C"},{Description: 'Brand D',Value: "ID_D"}
  ])
};

ko.applyBindings(vm);
select {
    width: 300px;
}
pre {
    position: absolute;
    top: 10px;
    right: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.1/knockout-latest.debug.js" integrity="sha512-per7WBYe3cT9aIDMoF74rYR7wpEDPqyncWqWzBGmJBnhp8H3ZD5fRdTM16IO5ePUEuBlH9DMKF7rHvuazhvDBA==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js" integrity="sha512-2ImtlRlf2VVmiGZsjm9bEyhjGW4dU7B6TNwh/hx/iSByxNENtj3WVE6o/9Lj4TJeVXPi4bnOIMXFIJJAeufa0A==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/css/select2.min.css" integrity="sha512-nMNlpuaDPrqlEls3IX/Q56H36qvBASwb3ipuo3MxeWbsQB1881ox0cRv7UPTgBlriqoynt35KjEwgGUeUXIPnw==" crossorigin="anonymous" />

<select data-bind="
  selectedOptions: BrandIds,options: Brands,optionsText: 'Description',optionsValue: 'Value',select2: {
    placeholder: 'Please Select...',allowClear: true,multiple: 'multiple'
  }
" multiple></select>

<pre data-bind="text: ko.toJSON($root,null,2)"></pre>

,

因此,事实证明与淘汰赛或select2无关。 我们建立了一个自定义连接,并将其发送到前端以绑定到我们的选择。 这里的字符串值是Guid的大写字符串表示形式。 用来绑定到selectedOptions的BrandIds包含所有小写的guid列表。 因此,可以归结为值不同的情况。