Angular 5 Material Table将filterPredicate替换为具有不同参数类型的函数

时间:2018-04-17 20:34:46

标签: angular typescript angular-material2 angular-cdk

我目前正在使用材质2表来显示某些数据的组件。我需要能够编写自定义过滤器操作(例如价格> 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参数是一个字符串。

所以我的问题是,如何在不重写材料2包中的函数的情况下将this.dataSource.filterPredicate替换为我的。有没有办法在打字稿中这样做?

如果有人知道为什么这样可行,尽管抛出了错误,哈哈会感兴趣

2 个答案:

答案 0 :(得分:3)

目前不支持此功能,但Github上有一个开放的feature request。它被添加到功能列表中,因此可能值得关注。

在此问题中,建议使用过滤器创建您自己的DataSource,该过滤器接受数组而不是字符串。请查看扩展MatTableDataSource类的DataSource

答案 1 :(得分:3)

作为解决方法,可以在设置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;
}