Select2 用字符串覆盖淘汰赛 observableArray

Posted

技术标签:

【中文标题】Select2 用字符串覆盖淘汰赛 observableArray【英文标题】:Select2 overwrites knockout observableArray with string 【发布时间】:2014-10-08 10:39:27 【问题描述】:

我正在使用带有自定义剔除绑定的 select2 来提供动态标记支持。不幸的是,当用户修改 select2 控件时,绑定的 observable 数组会被逗号分隔的值字符串覆盖,而不是简单地将新值添加到 observable 数组中。我猜这与我绑定输入值的方式有关,但我似乎找不到替代方法。任何帮助将不胜感激!

JSFiddle:http://jsfiddle.net/gk8a6sht/6/

javascript

ko.bindingHandlers.select2 = 
  init: function(element, valueAccessor) 
     var options = ko.toJS(valueAccessor()) || ;
     setTimeout(function()  
         $(element).select2(options);
     , 0);
   
;    

var viewModel = 
    values: ko.observableArray(["red", "grey", "blue"])
;

ko.applyBindings(viewModel);

html

<input data-bind="value: values, select2:  tags: values, tokenSeparators: [',', ' '] "/>

【问题讨论】:

我已经编辑了我的答案,现在看起来好多了。我希望这是你想要的。 你检查过答案了吗?如果有帮助,你能接受吗? 【参考方案1】:

编辑 2:

更正了以下代码中的 split 函数以使用指定的 tokenSeparators。 Fiddle 也更新了。

编辑:

我已经阅读了一些关于select2 插件及其标记支持的内容。据我了解,您已经将预定义的一组标签(在选项中设置)与用户选择的实际标签混合在一起。我已经显着更新了我的jsfiddle,现在绑定处理程序如下所示:

ko.bindingHandlers.select2 = 
    defaults: 
        value: ko.observable(),
        select2Options: 
            tags: ko.observableArray([]),
            tokenSeparators: [',', ' ']
        
    ,
    init: function(element, valueAccessor) 
        var bindingOptions = valueAccessor() || ,
            options =  $.extend(true, ,
                ko.bindingHandlers.select2.defaults,          
                bindingOptions),
            value = ko.utils.unwrapObservable(options.value);
        $(element).val(value);
        $(element).select2(ko.toJS(options.select2Options));
        $(element).change(function() 
            options.value($(element).val().split(options.select2Options.tokenSeparators));
        );
    ,
    update: function(element, valueAccessor) 
        ko.utils.unwrapObservable(valueAccessor());
        $(element).val(valueAccessor().value());
    
;

首先,为了方便起见,我添加了默认值,例如,您不必每次都指定标记分隔符。接下来,我已将标签选择的所有管道移至绑定处理程序,现在您的视图模型如下所示:

function ViewModel () 
    var self = this;
    self.predefinedValues= ko.observableArray();
    self.selectedValues = ko.observableArray();
;
ViewModel.prototype.init = function() 
    // Here we should init our model with values from server, for example
    this.predefinedValues(["red", "grey", "blue"]);
    this.selectedValues(["red"]);

所以现在你有 2 个可观察数组 - 第一个是预定义的标签集,第二个是实际选定标签的数组。

标记如下:

<input type="hidden" style="width: 300px" data-bind="select2:  value: selectedValues, select2Options:  tags: predefinedValues "/>

所以没有字符串了,一切都在绑定处理程序中完成。

原答案:

只需使用另一个 observable 来保留 select2 字符串的值,如下所示:

HTML:

<input data-bind="value: selectedValuesString, select2:  tags: values, tokenSeparators: [',', ' '] "/>

Javascipt:

function ViewModel () 
    var self = this;
    self.values= ko.observableArray(["red", "grey", "blue"]);
    self.selectedValuesString= ko.observable(self.values().join(","));
    self.selectedValuesString.subscribe(function(newValue) 
        self.values(newValue.split(','));
    );
;

我已将视图模型声明从对象更改为函数,因此编写订阅函数会更容易。

您还应该在自定义绑定中使用update 函数来响应列表更改。

我已更新您的 jsfiddle 以展示其工作原理。我添加了Add value 按钮,看看它如何与添加元素一起工作。我使用了一个随机数来添加新值,因为 select2 不喜欢我猜想的相似值(将它们视为一个值)。

【讨论】:

感谢您的详细回复和解决方案。这种方法当然适用于提供的标记分隔符。依赖 'split' 函数的缺点是,如果您在标签中允许逗号,它会失败(从 tokenSeparators 数组中删除 ',' 以查看)。这更多是关于 select2 如何更新输入的问题,您可以通过一些巧妙的 JavaScript 来克服这个问题。 @mindlessgoods,哎呀,我只是忽略了这一点。请参阅编辑后的答案,我已更新 fiddle link。我想现在它值得一票;)

以上是关于Select2 用字符串覆盖淘汰赛 observableArray的主要内容,如果未能解决你的问题,请参考以下文章

将 select2 与淘汰赛绑定

带有 ajax 的淘汰赛3+select2 (v4)

带有淘汰赛的Select2如何在选择中显示选定的项目?

Select2 在淘汰赛中选择标签作为对象而不是“id”

淘汰赛 3.1:Select2 无法与 valueAllowUnset 一起正常工作

在 jQuery 对话框中淘汰 'with' 绑定和 select2