从 Angular 中的多 select 下拉列表中选择并取消 selecting 值 7
Selecting and Unselecting values from a multi select dropdown in Angular 7
我制作了一个多 select 下拉菜单,其实现方式如下
MyFilter{
key: string; // uniquely identifies selected filter among many filters on page
order: number; // display order of filter on page
options: DropListOption[]; // options in a dropdown
values: DropListOption[]; // selected values from dropdown
}
DropListOption{
label: string; // name of option
value: any; //value of option
}
我实现了一个方法,当复选框被 selected 或取消selected 时调用,如下所示:
onSelect(key: string, option: DropListOption): void{
const filtersOpt = this.filters; // type of filter is MyFilter
filtersOpt.map((filter) => {
if(filter.key === key){
const selected: boolean = !!filter.values.find((opt) => opt.value === option.value);
filters.values = selected // filters.values used as property binding to display number of selected values
? filters.values.filter((opt) => opt.value !== option.value)
: [...filters.values, option];
}
return filter;
});
this.updateFilters.emit(filtersOpt); //emitting to parent component
}
虽然我的逻辑工作正常但对Angular/RxJS(前端开发)来说是新手,但我不太确定我的代码是否是好的代码。请你让我知道我们的想法或纠正我。如果有人能告诉我实现 onSelect() 方法的更好方法,我将不胜感激。
我不确定在您的 html 中是否可以进行任何改进以进一步简化此方法,因为您没有展示它,但坦率地说我会按以下方式进行。
解决方案 #1
This solution is not compatible with Internet Explorer due to the Array.prototype.findIndex() method usage. See Solution #2 for a compatible solution.
onSelect(key: string, option: DropListOption): void {
const filterOpt = this.filters.find(fil => fil.key === key);
if (!filterOpt) {
console.warn('No filter was found with the given key.');
return;
}
const selectedOptIdx = filterOpt.values.findIndex(opt => opt.value === option.value);
if (selectedOptIdx > -1) {
filters.splice(selectedOptIdx, 1);
} else {
filters.push(option);
}
}
优点
- 不太复杂的解决方案。
- 总体而言,可读性稍好。
解决方案 #2
onSelect(key: string, option: DropListOption): void {
const filterOpt = this.filters.find(fil => fil.key === key);
if (!filterOpt) {
console.warn('No filter was found with the given key.');
return;
}
const selectedOpt = filterOpt.values.find(opt => opt.value === option.value);
if (selectedOpt) {
filters.splice(filters.indexOf(selectedOpt), 1);
} else {
filters.push(option);
}
}
优点
- 与 Internet Explorer 兼容。
总的来说,我想说有一些更好的方法可以完成,我建议您阅读一些 Array.prototype 方法的复杂性,这样您就可以更好地理解您的选择一路走来,尝试更好地理解 Array.prototype.map() 方法的作用,尤其是。我会在下面留下来源。
来源
- splice 和 filter(以及 copyWithin)之间的性能比较。 (link)
- 关于 javascript 数组方法的复杂性的讨论。 (link)
Array.prototype.map() from MDN documentation pages (link)
(...) map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values (including undefined). (...)
我制作了一个多 select 下拉菜单,其实现方式如下
MyFilter{
key: string; // uniquely identifies selected filter among many filters on page
order: number; // display order of filter on page
options: DropListOption[]; // options in a dropdown
values: DropListOption[]; // selected values from dropdown
}
DropListOption{
label: string; // name of option
value: any; //value of option
}
我实现了一个方法,当复选框被 selected 或取消selected 时调用,如下所示:
onSelect(key: string, option: DropListOption): void{
const filtersOpt = this.filters; // type of filter is MyFilter
filtersOpt.map((filter) => {
if(filter.key === key){
const selected: boolean = !!filter.values.find((opt) => opt.value === option.value);
filters.values = selected // filters.values used as property binding to display number of selected values
? filters.values.filter((opt) => opt.value !== option.value)
: [...filters.values, option];
}
return filter;
});
this.updateFilters.emit(filtersOpt); //emitting to parent component
}
虽然我的逻辑工作正常但对Angular/RxJS(前端开发)来说是新手,但我不太确定我的代码是否是好的代码。请你让我知道我们的想法或纠正我。如果有人能告诉我实现 onSelect() 方法的更好方法,我将不胜感激。
我不确定在您的 html 中是否可以进行任何改进以进一步简化此方法,因为您没有展示它,但坦率地说我会按以下方式进行。
解决方案 #1
This solution is not compatible with Internet Explorer due to the Array.prototype.findIndex() method usage. See Solution #2 for a compatible solution.
onSelect(key: string, option: DropListOption): void {
const filterOpt = this.filters.find(fil => fil.key === key);
if (!filterOpt) {
console.warn('No filter was found with the given key.');
return;
}
const selectedOptIdx = filterOpt.values.findIndex(opt => opt.value === option.value);
if (selectedOptIdx > -1) {
filters.splice(selectedOptIdx, 1);
} else {
filters.push(option);
}
}
优点
- 不太复杂的解决方案。
- 总体而言,可读性稍好。
解决方案 #2
onSelect(key: string, option: DropListOption): void {
const filterOpt = this.filters.find(fil => fil.key === key);
if (!filterOpt) {
console.warn('No filter was found with the given key.');
return;
}
const selectedOpt = filterOpt.values.find(opt => opt.value === option.value);
if (selectedOpt) {
filters.splice(filters.indexOf(selectedOpt), 1);
} else {
filters.push(option);
}
}
优点
- 与 Internet Explorer 兼容。
总的来说,我想说有一些更好的方法可以完成,我建议您阅读一些 Array.prototype 方法的复杂性,这样您就可以更好地理解您的选择一路走来,尝试更好地理解 Array.prototype.map() 方法的作用,尤其是。我会在下面留下来源。
来源
- splice 和 filter(以及 copyWithin)之间的性能比较。 (link)
- 关于 javascript 数组方法的复杂性的讨论。 (link)
Array.prototype.map() from MDN documentation pages (link)
(...) map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results. callback is invoked only for indexes of the array which have assigned values (including undefined). (...)