简体   繁体   中英

Angular 5 Material Table replace filterPredicate with function that has different parameter types

I'm currently working on a component that uses the material 2 table to show some data. I need to be able to write custom filter operations (eg price > 1) and combine multiple filters. To make that work i wrote a custom 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
} 

a interface for the predicate type:

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

The customFilterPredicate loops through all the filters the where passed as parameter and returns true if all conditions have been met and false if one or more have not.

Now I use this function to get the data for the table via service, set my dataSource and replace the filterPredicate of the dataSource:

  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;
    })
  }

To funny thing is that the filtering works when I use it, but it always throws an error saying that I cant replace the filterPredicate with my custom one, since it expects the filter parameter to be a string.

So my question is, how can I replace this.dataSource.filterPredicate with mine, without rewriting the function in the material 2 package. Is there a way to do this in typescript?

And if anyone has an idea why this works, despite throwing the error, that would be interesting to haha

This is currently not supported but there is an open feature request on Github. It was added to the features list, so it might be worth following.

In the issue, it is suggested to create your own DataSource with a filter that accepts arrays instead of strings. Have a look at the MatTableDataSource which extends the DataSource class.

As a workaround you could use bind() when setting the filterPredicate:

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

Then you get access to local variables, in my case:

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);
}

In your case it would be the array of predicates. However, whenever any of the predicates change you need to update the value for filter, it is only when that changes is the filter reapplied.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM