Select2 Knockout 多选设置值问题

Posted

技术标签:

【中文标题】Select2 Knockout 多选设置值问题【英文标题】:Select2 Knockout nulti-select setting value issue 【发布时间】:2020-12-01 20:39:21 【问题描述】:

所以我有许多使用 Knockout 绑定的 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, valueAccessor, 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");
    
;

selectedoptions 绑定到一个 Guid 列表。这是javascript端的字符串列表。 我相信 Select2 选择需要字符串才能设置选定的值。

我的选择如下所示:

<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

]

【问题讨论】:

如果你还没有写过这个绑定处理程序(你还没有写过),请链接到你使用过的源代码,以供参考和表扬。 【参考方案1】:

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

Knockout 操纵隐藏在背景中的原始&lt;select&gt; 元素,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>

【讨论】:

感谢您的评论。我将按照建议删除更新。如果不需要 @LudwigNel 对于您的下一个问题,请制作一个像上面那样的可运行示例,以重现您看到的问题/错误。当人们不必猜测您的代码时,他们更容易弄清楚发生了什么。 我会确保将来有一个可运行的示例。对此感到抱歉【参考方案2】:

所以结果证明与淘汰赛或select2无关。 我们有一个自定义连接,我们建立并发送到前端以绑定到我们的选择。 这里的字符串值是 guid 的大写字符串表示。 用于绑定到 selectedOptions 的 BrandIds 包含一个全小写的 guid 列表。 所以归结为价值观不同的情况。

【讨论】:

以上是关于Select2 Knockout 多选设置值问题的主要内容,如果未能解决你的问题,请参考以下文章

Knockout Select2 按对象设置初始值

Select2 与 Knockout.js 初始值

使用 jQuery 的 select2 向多选添加值

select2插件多选不换行

Select2 多选和允许标签的默认值

Knockout.js Select2 绑定。将 Select2 升级到 v4 后损坏