Mat-Table中的自定义筛选器

39

我正在使用mat-table。它有一个筛选器,与doc示例配合得很好:

https://material.angular.io/components/table/overview,原始代码如下:

    <div class="example-header">
       <mat-form-field>
         <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
       </mat-form-field>
   </div>

   <mat-table #table [dataSource]="dataSource">
      <!-- the rest of the code -->
   </mat-table>
    export class TableFilteringExample {
     displayedColumns = ['position', 'name', 'weight', 'symbol'];
     dataSource = new MatTableDataSource(ELEMENT_DATA);

     applyFilter(filterValue: string) {
       filterValue = filterValue.trim(); // Remove whitespace
       filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
       this.dataSource.filter = filterValue;
     }
    }
    const ELEMENT_DATA: Element[] = [
     {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
     {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
     {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
     {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
     {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}
    ]; 

通过这种实现方式,当过滤时,它会过滤所有列。

现在我想要更改过滤器,只想过滤"名称"列,因此我正在尝试重写过滤器并将其分配给filterData。

      applyFilter(filterValue: string) {
        filterValue = filterValue.trim(); // Remove whitespace
        filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
       this.dataSource.filteredData = this.filterByEmail(filterValue); 
        console.log(this.dataSource.filteredData); //value is what I want.
    }

    filterByName(filter: string): any {
      const dataFiltered = this.data.filter(function(item){
         return item.name.indexOf(filter) > -1
       })
        return dataFiltered;
    }

在控制台中,我可以看到this.dataSource.filteredData具有我想要打印的数据,但是表格没有重新加载。

我错过了什么?

4个回答

57

我在这里找到了解决方案

需要重写filterPredicate,并像以往一样使用它,当筛选通过时,filterPredicate需要返回true,当筛选不通过时,需要返回false

export interface Element {
 name: string;
 position: number;
 weight: number;
 symbol: string;
}


dataSource = new MatTableDataSource(ELEMENT_DATA);
/* configure filter */
this.dataSource.filterPredicate = 
  (data: Element, filter: string) => data.name.indexOf(filter) != -1;


applyFilter(filterValue: string) {
   filterValue = filterValue.trim(); // Remove whitespace
   filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
   this.dataSource.filter = filterValue;
 }

1
在 ngOnInit() 方法中添加以下代码:this.dataSource.filterPredicate = (data: Element, filter: string) => data.name.indexOf(filter) != -1;然后 IDE 显示如下错误信息:TS2322:类型“(data: Element, filter: string) => boolean”不能赋值给类型“(data: string, filter: string) => boolean”。参数“data”的类型与“data”的类型不兼容。类型“string”不能赋值给类型“Element”。有人知道为什么吗? - munificent

15

别忘了在你的数据上应用 .trim().toLowerCase(),否则你可能会遇到意想不到的结果。看看我下面的例子:

this.dataSource.filterPredicate = (data:
  {name: string}, filterValue: string) =>
  data.name.trim().toLowerCase().indexOf(filterValue) !== -1;

applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.trim().toLowerCase();
}

2
请注意,类中显示在表行中的所有字段都会受到过滤,即使您不将该字段显示为列。
export class City {
  id: number;//is not displayed in mat table
  code: string;
  name: string;
  country:Country;
}

任何应用于城市表数据源的筛选器也会应用于id列,一般情况下我们不向最终用户显示该列。
//this filter will also apply to id column
this.cityDataSource.filter = filterValue;

1
如何避免ID被过滤器过滤? - Amit Kumawat
数据源的过滤谓词可以按如下所述使用。 - Selman Gun

1
当使用父子组件(或带有observable的服务)时,您必须始终在包含MatTableDataSource的组件中设置"applyFilter"函数(名称不重要)。在表格组件中,我添加了@Input来作为FormControl传递筛选字符串值,并发送一个筛选函数(filterfn)。
  @Input() data: any[];
  @Input() filterControl: FormControl;
  @Input() filterfn: (data: any, filter: string) => boolean;

在初始化中。
 ngOnInit(): void {
    this.dataSource.filterPredicate = this.filterfn
    this.dataSource.data = this.data;
    this.initExpandedDefaultValues();
    //my "applyFilter"
    this.filterControl.valueChanges.subscribe(searchValue => this.dataSource.filter = searchValue)
  }

在父HTML中
<div *ngIf="users">
    <expended-table [data]="users"
        [filterfn]="filterFunction"
        [filterControl]="search">
    </expended-table>
</div>

在父组件中。
public users:User[]
  search:FormControl = new FormControl()
  public usersFiltered:User[]

  filterFunction(u: User, searchValue: string) : boolean{
    if (searchValue) {
      let v = searchValue.trim().toLowerCase()
      if (
        u.firstName.toLowerCase().includes(v) || 
        u.lastName.toLowerCase().includes(v) || 
        //bla bla bla more tests
        u.permission.toLowerCase().includes(v)  
      )
      { return true } 
      else { return false}
    } //end if searchValue
    else 
    {
      return true
    }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接