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