Select2用字符串覆盖knockout observableArray

min*_*ods 2 javascript jquery knockout.js jquery-select2

我正在使用带有自定义knockout绑定的select2来提供动态标记支持.不幸的是,当用户修改select2控件时,绑定的可观察数组会被逗号分隔的值字符串覆盖,而不是简单地将新值添加到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);
Run Code Online (Sandbox Code Playgroud)

HTML:

<input data-bind="value: values, select2: { tags: values, tokenSeparators: [',', ' '] }"/>
Run Code Online (Sandbox Code Playgroud)

Ily*_*nin 6

编辑2:

修正split了下面代码中使用指定的功能tokenSeparators.小提琴也更新了.

编辑:

我已经阅读了一些关于select2插件及其Tagging支持的内容.据我了解,您已经将预定义的一组标签(在选项中设置)与用户选择的实际标签混合在一起.我已经大大更新了我的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());
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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"]);
}
Run Code Online (Sandbox Code Playgroud)

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

标记看起来如下:

<input type="hidden" style="width: 300px" data-bind="select2: { value: selectedValues, select2Options: { tags: predefinedValues }}"/>
Run Code Online (Sandbox Code Playgroud)

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

原始答案:

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

HTML:

<input data-bind="value: selectedValuesString, select2: { tags: values, tokenSeparators: [',', ' '] }"/>
Run Code Online (Sandbox Code Playgroud)

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(','));
    });
};
Run Code Online (Sandbox Code Playgroud)

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

此外,您应该使用update自定义绑定中的函数来响应列表更改.

我已经更新了你的jsfiddle来展示它是如何工作的.我添加了Add value按钮,看看它如何与添加元素一起工作.我使用随机数来添加新值,因为select2不喜欢类似的值我猜(将它们视为一个值).