如何实现多个 select 列表以确保只有唯一值可供所有人使用?

How do I implement multiple select lists ensuring only unique values are available to all?

我需要确保我的 select 列表中的唯一性。

我有可用选项列表:

var viewModel = 
{
    availableOptions : ['Bicycle','Car','Shuttle','Motorcycle','Motorcycle'],
    items : [{id:1, selectedOption: ko.observable('Car')}, 
             {id:2, selectedOption: ko.observable()}, 
             {id:3, selectedOption: ko.observable()}]
}

我想遍历我的项目,但要确保没有两个项目可以有相同的选项:

<-- ko foreach: items -->
  <select data-bind="options: $parent.availableOptions, value: selectedOption, optionsCaption: 'Choose...'"></select>
<!-- /ko -->

关于如何在默认值不变的情况下成功实现此目的的任何想法,并且只有其余选项可供我的其他 select 使用?

试试下面的方法 -

selectedOption.subscribe(function (newValue) {
    var index = availableOptions.indexOf(selectedOption());
    if (index > -1) {
        availableOptions.splice(index, 1);
    }
});

最干净的方法当然是首先不向浏览器发送无用的重复数据。

下一个最佳解决方案是使用数组唯一函数。大多数 JS 库都提供这样的功能。没有特别的原因,我正在使用 lodash's uniq() but you can use any library you like, for example jQuery's $.unique().

var viewModel = {
    availableOptions : _.uniq(['Bicycle','Car','Shuttle','Motorcycle','Motorcycle']),
    items : [{id:1, selectedOption: ko.observable('Car')}, 
             {id:2, selectedOption: ko.observable()}, 
             {id:3, selectedOption: ko.observable()}]
};

一般来说,我建议您对视图模型使用 class,这样您就可以在构建它时进行某种处理。将对象文字用于视图模型仅适用于最简单的情况。

比如这样。

function ViewModel(data) {
    var self = this, i;

    self.availableOptions: ko.observableArray(_.uniq(data.availableOptions));
    self.items = ko.observableArray();

    for(i = 1; i <= data.itemCount; i++) {
        self.items.push({id:i, selectedOption: ko.observable()});
    }
}

var viewModel = new ViewModel({
    availableOptions: ['Bicycle','Car','Shuttle','Motorcycle','Motorcycle'],
    itemCount: 3
});
ko.applyBindings(viewModel);

您需要 computed 在这里过滤每个 select

的项目
this.availableOptions = ko.computed(function () {
    var item, option, i, j, isAvailable, result = [];
    for (i = 0; i < root.availableOptions.length; i++) {            
        option = root.availableOptions[i];
        isAvailable = true;
        for (j = 0; j < root.items.length; j++) {
            item = root.items[j];
            if (item.id !== this.id && item.selectedOption() === option) {
                isAvailable = false;
            }
        }
        if (isAvailable) {
            result.push(option);
        }
    }
    return result;
}, this, { deferEvaluation: true });   

working fiddle

已编辑 添加了 deferEvaluation 以使所有项都依赖于所有项