【问题标题】:custom filter in mat-tablemat-table 中的自定义过滤器
【发布时间】:2018-07-08 11:08:18
【问题描述】:

我正在使用垫表。它有一个过滤器,适用于文档示例:

来自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 有我要打印的数据,但表没有重新加载。

我错过了什么?

【问题讨论】:

    标签: angular angular-material angular-material2 angular-cdk


    【解决方案1】:

    我找到了解决方案here

    需要重写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;
     }
    

    【讨论】:

    • 添加 this.dataSource.filterPredicate = (data: Element, filter: string) => data.name.indexOf(filter) != -1;在 ngOnInit() 方法中,IDE 显示:TS2322:类型“(数据:元素,过滤器:字符串)=>布尔”不可分配给类型“(数据:字符串,过滤器:字符串)=>布尔”。参数 'data' 和 'data' 的类型不兼容。类型“字符串”不可分配给类型“元素”。有人知道为什么吗?
    【解决方案2】:

    不要忘记对您的数据应用.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();
    }
    

    【讨论】:

      【解决方案3】:

      请注意,显示在表格行中的类的所有字段都需要过滤,即使您没有将该字段显示为列。

      export class City {
        id: number;//is not displayed in mat table
        code: string;
        name: string;
        country:Country;
      }
      

      city表的dataSource的任何过滤器,同样适用于id列,一般我们不会显示给最终用户。

      //this filter will also apply to id column
      this.cityDataSource.filter = filterValue;
      

      【讨论】:

      • 如何避免过滤器中的id?
      • 数据源的filterPredicate可以如下所述使用。
      【解决方案4】:

      当使用父子组件(或带有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
          }
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-05
        • 2019-10-10
        • 2019-06-22
        • 1970-01-01
        • 2020-01-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多