从 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). (...)