Jquery KnockoutJS自定义绑定从multi-select获取逗号分隔的值

Jquery KnockoutJS自定义绑定从multi-select获取逗号分隔的值,jquery,knockout.js,Jquery,Knockout.js,我的html中有以下select: <select class="form-control" data-bind="multiSelectCommaSeparated: CityIds, options: $root.Cities, optionsText: 'CityName', optionsValue: 'CityId', valueUpdate: 'change'" multiple="true"></select> 用户选择前3个城市,然后我的可观测值应该是1

我的html中有以下
select

<select class="form-control" data-bind="multiSelectCommaSeparated: CityIds, options: $root.Cities, optionsText: 'CityName', optionsValue: 'CityId', valueUpdate: 'change'" multiple="true"></select>
用户选择前3个城市,然后我的可观测值应该是
1,2,3
。如果用户取消选择
City 3
,则可观察对象应具有
1,2
,并且这应在用户在
select
中选择/取消选择任何值时立即发生

我使用问题中的引用编写了以下自定义绑定:

ko.bindingHandlers.multiSelectCommaSeparated = {
    init: function (element, valueAccessor) {
        var selMulti = $.map($(element.id + " option:selected"), function (el, i) {
            return $(el).text();
        });
        valueAccessor(selMulti);
    },
    update: function (element, valueAccessor) {
        var selMulti = $.map($(element.id + " option:selected"), function (el, i) {
            return $(el).text();
        });
        valueAccessor(selMulti);
    }
}
在上述自定义绑定中,当我在
多选下拉列表中更改选择时,更新事件不会触发。我应该如何更改自定义绑定以达到我的要求?

我不是很直截了当地回答您的问题,其他人(甚至我)可能会在单独的回答中这样做。相反,让我提出另一种方法来处理这个问题,即IMHO更适合Knockout的MVVM风格

构造视图模型以将所需的CSV字符串作为一个字符串保存。例如:

var ViewModel = function() {
    var self = this;

    self.Cities = [
        {CityId: 1, CityName: "City 1"},
        {CityId: 2, CityName: "City 2"},
        {CityId: 3, CityName: "City 3"},
        {CityId: 4, CityName: "City 4"}
    ];

    self.SelectedCities = ko.observableArray([]);

    self.SelectedCitiesCsv = ko.computed(function(){
        return self.SelectedCities().join(",");
    });
};
您可以使用此视图对此进行测试:



CSV:

请参见演示

与自定义绑定相比,此方法的优点包括:

  • 单元可测试
  • 不需要定制绑定
  • Knockout使我们的CSV字符串与视图保持同步,不需要自定义代码
  • 不需要依赖jQuery,如果可能的话,利用KO让JS不知道实际的DOM(这再次提高了可测试性)

如果没有为viewmodels使用构造函数,而是为普通javascript对象使用构造函数,则必须在创建具有基本属性的对象后添加计算的可观察对象。大概是这样的:

var viewModel =  {
    Cities :[
        {CityId: 1, CityName: "City 1"},
        {CityId: 2, CityName: "City 2"},
        {CityId: 3, CityName: "City 3"},
        {CityId: 4, CityName: "City 4"}
    ],

    SelectedCities : ko.observableArray([])
};

viewModel.SelectedCitiesCsv = ko.computed(function(){
    return viewModel.SelectedCities().join(",");
});
或者看看。

我不是很直截了当地回答你的问题,其他人(甚至我)可能会在单独的回答中这样做。相反,让我提出另一种方法来处理这个问题,即IMHO更适合Knockout的MVVM风格

构造视图模型以将所需的CSV字符串作为一个字符串保存。例如:

var ViewModel = function() {
    var self = this;

    self.Cities = [
        {CityId: 1, CityName: "City 1"},
        {CityId: 2, CityName: "City 2"},
        {CityId: 3, CityName: "City 3"},
        {CityId: 4, CityName: "City 4"}
    ];

    self.SelectedCities = ko.observableArray([]);

    self.SelectedCitiesCsv = ko.computed(function(){
        return self.SelectedCities().join(",");
    });
};
您可以使用此视图对此进行测试:



CSV:

请参见演示

与自定义绑定相比,此方法的优点包括:

  • 单元可测试
  • 不需要定制绑定
  • Knockout使我们的CSV字符串与视图保持同步,不需要自定义代码
  • 不需要依赖jQuery,如果可能的话,利用KO让JS不知道实际的DOM(这再次提高了可测试性)

如果没有为viewmodels使用构造函数,而是为普通javascript对象使用构造函数,则必须在创建具有基本属性的对象后添加计算的可观察对象。大概是这样的:

var viewModel =  {
    Cities :[
        {CityId: 1, CityName: "City 1"},
        {CityId: 2, CityName: "City 2"},
        {CityId: 3, CityName: "City 3"},
        {CityId: 4, CityName: "City 4"}
    ],

    SelectedCities : ko.observableArray([])
};

viewModel.SelectedCitiesCsv = ko.computed(function(){
    return viewModel.SelectedCities().join(",");
});

或者请参见。

我正试图在视图模型中使用这种方法,但我面临一个问题。我已修改了您的小提琴以演示此问题:。我已经用这种格式编写了我的整个视图模型,那么是否有其他方法可以使用这种语法编写
computed
observatives?在vm之外编写:
ViewModel.SelectedCitiesCsv=ko.computed(function(){return ViewModel.SelectedCities().join(,“”;})尽管我建议使用基于构造函数的viewmodels,如我的第一个示例中所示。您可以使用@GôTô的建议,也可以将计算出的可观测值添加到普通javascript对象中,如果您在第二步中添加它们的话。关于这方面的提示,请参阅我的答案修改。我完全同意使用基于函数的方法viewmodels@Jeroen改进后的小提琴正在工作。我只想问一个问题,哪种类型的剔除视图模型声明更好,基于
函数
还是像我现在使用的
普通JS对象
?如果我使用基于
函数的视图模型,那么我如何引用视图模型之外的可观察对象?链接到这方面的某类文章将非常有用:)我试图在我的视图模型中使用这种方法,但我面临一个问题。我已修改了您的小提琴以演示此问题:。我已经用这种格式编写了我的整个视图模型,那么是否有其他方法可以使用这种语法编写
computed
observatives?在vm之外编写:
ViewModel.SelectedCitiesCsv=ko.computed(function(){return ViewModel.SelectedCities().join(,“”;})尽管我建议使用基于构造函数的viewmodels,如我的第一个示例中所示。您可以使用@GôTô的建议,也可以将计算出的可观测值添加到普通javascript对象中,如果您在第二步中添加它们的话。关于这方面的提示,请参阅我的答案修改。我完全同意使用基于函数的方法viewmodels@Jeroen改进后的小提琴正在工作。我只想问一个问题,哪种类型的剔除视图模型声明更好,基于
函数
还是像我现在使用的
普通JS对象
?如果我使用基于
函数的视图模型,那么我如何引用视图模型之外的可观察对象?链接到这方面的某种文章将非常有用:)