knockout:当选择其他时,从多选控件中删除一个元素

时间:2015-01-21 14:41:44

标签: javascript knockout.js

我使用淘汰赛并且我有一个项目列表,让我们说:

Tomato,
Potato,
Broccoli, 
Bean

允许用户从多选表格控件中选择所有这些项目。

<select class="form-control" multiple
  data-bind="selectPicker: Types,
  optionsText: 'Name',
  optionsValue: 'VegetableTypeId',
  selectPickerOptions: { optionsArray: AvailableVegetableTypes }">
</select>

除一种情况外 - 当用户选择番茄时,马铃薯应该取消选择。 我试图在所选项目数组上使用订阅:

this.Types.subscribe(changes => {
        var VegetableTypes = this.AvailableVegetablesTypes();
        var company = VegetableTypes.First(element => element.VegetableTypeId == changes[0].value);
        if (changes[0].status == "added") {
            if (Vegetable.IsTomato) {
                this.Types.remove(element =>
                    VegetableTypes.First(baseElement =>
                        baseElement.VegetableTypesTypeId == element && baseElement.IsPotato));
            } else if (Vegetable.IsPotato) {
                this.Types.remove(element =>
                    VegetableTypes.First(baseElement =>
                        baseElement.VegetableTypesTypeId == element && baseElement.IsTomato));
            }
        }
    }, null, "arrayChange");

问题是我使用了ObservableArray.Remove,因此在当前运行完成之前它再次调用我的函数。这应该不是问题,因为删除后第一次更改是&#34;删除&#34;类型,所以不应该执行整个逻辑。

但在此之后,当我再次选择番茄/土豆时,什么都没有被烧制。最后我实际选择了番茄和土豆。 然后,当我取消选择这两个中的一个并再次选择它时,一切正常,然后整个情况重复。

你有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我不明白你为什么使用selectPicker绑定而不是普通optionsselectedOptions绑定available in Knockout

但是,我构建了一个实现所需行为的简单演示。你可以在这里找到它:

http://jsbin.com/fofojaqohi/1/edit?html,js,console,output

请注意,每当您选择番茄之后的番茄时,马铃薯将被取消选择。

您走在正确的轨道上:您需要订阅所选项目的数组并检查是否存在任何无效选择。我希望这会有所帮助。

供参考,以下是代码:

HTML:

<select class="form-control" multiple="true"
  data-bind="options: availableVegetableTypes, selectedOptions: selected">
</select>

JS:

var availableVegetableTypes = ['Tomato',
'Potato',
'Broccoli', 
'Bean'];

var selected = ko.observableArray();

var unselectMap = {
  'Tomato': 'Potato'
};

selected.subscribe(function(selectedOptions){
  var keysToUnselect = [];
  console.log("Selected", selectedOptions);
  selectedOptions.forEach(function(selectedOption){
    if (unselectMap[selectedOption] != null) {
      // This key exists in the unselect map
      // Let's check if the value is in the array
      if (_.contains(selectedOptions, unselectMap[selectedOption])) {
        // The invalid key exists. Let's mark it for removal.
        keysToUnselect.push(unselectMap[selectedOption]);
      }
    }
  });
  if (keysToUnselect.length > 0) { 
    console.log("Unselect", keysToUnselect);
    var reject = function(v){
      return _.contains(keysToUnselect, v);
    };
    filteredSelectedOptions = _.reject(selectedOptions, reject);
    console.log("Filtered", filteredSelectedOptions);
    selected(filteredSelectedOptions);
  }
});

ko.applyBindings({
  availableVegetableTypes:availableVegetableTypes,
  selected: selected
});