敲除:在选择另一个元素时从多选控件中删除一个元素
knockout: remove one element from multiselect control when other is selected
我正在使用淘汰赛并且我有一个项目列表,比方说:
Tomato,
Potato,
Broccoli,
Bean
所有这些项目都允许用户从 multiselect 表单控件select。
<select class="form-control" multiple
data-bind="selectPicker: Types,
optionsText: 'Name',
optionsValue: 'VegetableTypeId',
selectPickerOptions: { optionsArray: AvailableVegetableTypes }">
</select>
除了一种情况 - 当用户 select 的番茄时,土豆应该不 select。
我试图在 selected 项目数组上使用订阅:
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,所以它会在当前 运行 完成之前再次调用我的函数。这应该不是问题,因为删除后第一个变化是 "deletion" 类型,所以整个逻辑不应该被执行。
但在这之后,当我再次 select tomato/potato 时,什么都没有被触发。 最后我实际上同时拥有番茄和土豆 select编辑。
然后,当我 deselect 这两个中的一个并再次 select 时,一切正常,然后整个情况重复。
你有什么想法吗?
我不明白你为什么使用 selectPicker
绑定而不是正常的 options
和 selectedOptions
绑定 available in Knockout.
但是,我构建了一个实现所需行为的简单演示。您可以在这里找到它:
http://jsbin.com/fofojaqohi/1/edit?html,js,console,output
请注意,每当您在 Potato 之后 select Tomato 时,Potato 将变得未selected。
您的方向是对的:您需要订阅 selected 项的数组并检查是否有任何无效的 selection。希望对您有所帮助。
供参考,这里是代码:
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
});
我正在使用淘汰赛并且我有一个项目列表,比方说:
Tomato,
Potato,
Broccoli,
Bean
所有这些项目都允许用户从 multiselect 表单控件select。
<select class="form-control" multiple
data-bind="selectPicker: Types,
optionsText: 'Name',
optionsValue: 'VegetableTypeId',
selectPickerOptions: { optionsArray: AvailableVegetableTypes }">
</select>
除了一种情况 - 当用户 select 的番茄时,土豆应该不 select。 我试图在 selected 项目数组上使用订阅:
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,所以它会在当前 运行 完成之前再次调用我的函数。这应该不是问题,因为删除后第一个变化是 "deletion" 类型,所以整个逻辑不应该被执行。
但在这之后,当我再次 select tomato/potato 时,什么都没有被触发。 最后我实际上同时拥有番茄和土豆 select编辑。 然后,当我 deselect 这两个中的一个并再次 select 时,一切正常,然后整个情况重复。
你有什么想法吗?
我不明白你为什么使用 selectPicker
绑定而不是正常的 options
和 selectedOptions
绑定 available in Knockout.
但是,我构建了一个实现所需行为的简单演示。您可以在这里找到它:
http://jsbin.com/fofojaqohi/1/edit?html,js,console,output
请注意,每当您在 Potato 之后 select Tomato 时,Potato 将变得未selected。
您的方向是对的:您需要订阅 selected 项的数组并检查是否有任何无效的 selection。希望对您有所帮助。
供参考,这里是代码:
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
});