网站搜索

typescript - Angular 5 Material 表格用具有不同参数类型的函数替换 filterPredicate


我目前正在开发一个使用 Material 2 表格来显示一些数据的组件。我需要能够编写自定义过滤操作(例如 price > 1)并组合多个过滤器。为了实现这一点,我编写了一个自定义的 filterPredicate:

customFilterPredicate(data: Coin, filters: Predicate[]): boolean {
  var operators = {
    '>=': function(a, b){
      return +a >= +b
    },
    '<=': function(a, b){
      return +a <= +b
    }
  }

  if(filters.length == 0) return true;
  let res = false;

  for(var i = 0; i < filters.length; i++){
    let conditionMet = operators[filters[i].op](data[filters[i].columnName], filters[i].val);
    if(conditionMet) {
      res = true;
    } else {
      res = false;
      break;
    }
  }
  return res
} 

谓词类型的接口:

export interface Predicate {
  field: columnName
  op: string;
  val: number;
  visible: boolean;
}

customFilterPredicate 会遍历作为参数传入的所有过滤器,如果所有条件都满足则返回 true,如果有一个或多个条件未满足则返回 false。

现在我使用这个函数通过服务获取表格的数据,设置我的 dataSource 并替换 dataSource 的 filterPredicate:

  setData(){
    return new Promise((resolve, reject) => {
      return this.coinService.getCoins()
      .subscribe(coins => {
          resolve(coins)
        })
    })
    .then((data: Coin[]) => {
      this.dataSource = new MatTableDataSource<Coin>(data);
      this.dataSource.filterPredicate = this.customPredicate;
    })
  }

有趣的是,当我使用它时过滤功能是有效的,但它总是抛出一个错误,说我不能用自定义的替代 filterPredicate,因为它期望 filter 参数是一个字符串。

所以我的问题是,我如何在不重写 material 2 包中的函数的情况下,用我自己的函数替换 this.dataSource.filterPredicate?在 TypeScript 中有办法做到吗?

如果有人知道为什么这会起作用,尽管会报错,那就很有趣了,哈哈

答案#1

这目前不被支持,但在 Github 上有一个公开的功能请求。它已被添加到功能列表中,所以可能值得关注。

在这个问题中,建议创建你自己的 DataSource,并使用一个接受数组而不是字符串的过滤器。看看扩展了 DataSource 类的 MatTableDataSource。

答案#2

作为一种变通方法,你可以在设置 filterPredicate 时使用 bind():

    this.dataSource.filterPredicate = this.customFilterPredicate.bind(this);

然后你可以访问局部变量,在我的例子中:

customFilterPredicate(data: Area, filter: string): boolean {
    return this.filterMatchesString(JSON.stringify(data), this.searchFilter) &&
        this.filterMatchesString(data.Area, this.areaFilter) &&
        this.filterMatchesString(data.Abbreviation, this.abbreviationFilter);
}

在你的情况下,它将是谓词数组。然而,每当任何谓词发生变化时,你都需要更新 filter 的值,只有当它发生变化时,filter 才会重新应用。

filterChange() {
    this.dataSource.filter = this._searchFilter + this._areaFilter + this._abbreviationFilter;
}