在角度 5 中过滤 Angular Material 表中的特定列 [重复]

Posted

技术标签:

【中文标题】在角度 5 中过滤 Angular Material 表中的特定列 [重复]【英文标题】:Filtering specific column in Angular Material table in angular 5 [duplicate] 【发布时间】:2018-06-24 21:01:08 【问题描述】:

Angular 材质官网中提到 filterPredicate: ((data: T, filter: string) => boolean) 将根据特定字段过滤数据。但不知道如何开始。

我看到了例子但没有得到:-https://stackblitz.com/edit/angular-material2-table?file=app%2Fapp.component.html

默认情况下它基于整个对象进行过滤,但我只想基于 json 的单个属性进行搜索。

【问题讨论】:

【参考方案1】:

这对我有帮助:

https://www.freakyjolly.com/angular-material-table-custom-filter-using-select-box/#.YB4GBugzbIU

如果你想在所有选择字段上都有“和”条件,那么有一个数组 - foundThisField[], 而不是 boolean found = true/false

例如。 foundThisField : number = []

如果找到字段/列/属性,则执行 foundThisField.push(1) 或 foundThisField.push(0)

最后,返回 foundThisField.includes(0)?false:true

【讨论】:

【参考方案2】:

每列的工作过滤器,演示链接Stackblitz。

要过滤 mat-table 中的特定列,请为该列添加一个搜索字段,如下所示;

<mat-form-field class="filter" floatLabel="never">
    <mat-label>Search</mat-label>
    <input matInput [formControl]="nameFilter">
  </mat-form-field>

我们将输入从 ReactiveFormsModule 连接到 FormControls。

    filterValues = 
    name: '',
    id: '',
    colour: '',
    pet: ''
 ;

我们将观察过滤器输入的值,并在它们发生变化时修改此过滤器对象和数据源的过滤器属性。我们必须将过滤器对象的字符串化版本分配给数据源的过滤器属性

    ngOnInit() 
    this.nameFilter.valueChanges
      .subscribe(
        name => 
          this.filterValues.name = name;
          this.dataSource.filter = JSON.stringify(this.filterValues);
        
      )
    this.idFilter.valueChanges
      .subscribe(
        id => 
          this.filterValues.id = id;
          this.dataSource.filter = JSON.stringify(this.filterValues);
        
      )
    this.colourFilter.valueChanges
      .subscribe(
        colour => 
          this.filterValues.colour = colour;
          this.dataSource.filter = JSON.stringify(this.filterValues);
        
      )
    this.petFilter.valueChanges
      .subscribe(
        pet => 
          this.filterValues.pet = pet;
          this.dataSource.filter = JSON.stringify(this.filterValues);
        
      )
  

我们必须更改数据源的 filterPredicate 来告诉它如何解释过滤器信息。

    constructor() 
    this.dataSource.data = this.people;
    this.dataSource.filterPredicate = this.tableFilter();
    

    tableFilter(): (data: any, filter: string) => boolean 
    let filterFunction = function(data, filter): boolean 
      let searchTerms = JSON.parse(filter);
      return data.name.toLowerCase().indexOf(searchTerms.name) !== -1
        && data.id.toString().toLowerCase().indexOf(searchTerms.id) !== -1
        && data.colour.toLowerCase().indexOf(searchTerms.colour) !== -1
        && data.pet.toLowerCase().indexOf(searchTerms.pet) !== -1;
    
    return filterFunction;

 

【讨论】:

很高兴它帮助了你【参考方案3】:

使用 filterPredicate 覆盖使用 customFilter()

的过滤器逻辑

演示Link

来源Link

        ...
        ngOnInit() 
            this.getRemoteData();

            // Overrride default filter behaviour of Material Datatable
            this.dataSource.filterPredicate = this.createFilter();
        
        ...

        // Custom filter method fot Angular Material Datatable
        createFilter() 
            let filterFunction = function (data: any, filter: string): boolean 
            let searchTerms = JSON.parse(filter);
            let isFilterSet = false;
            for (const col in searchTerms) 
                if (searchTerms[col].toString() !== '') 
                isFilterSet = true;
                 else 
                delete searchTerms[col];
                
            

            let nameSearch = () => 
                let found = false;
                if (isFilterSet) 
                for (const col in searchTerms) 
                    searchTerms[col].trim().toLowerCase().split(' ').forEach(word => 
                    if (data[col].toString().toLowerCase().indexOf(word) != -1 && isFilterSet) 
                        found = true
                    
                    );
                
                return found
                 else 
                return true;
                
            
            return nameSearch()
            
            return filterFunction
        

【讨论】:

【参考方案4】:

为了扩展Naresh's answer,以下 HTML sn-p 显示了如何在同一列中进行排序和过滤,以及用于清除过滤条件的小“x”按钮:

   <ng-container matColumnDef="description">
    <th mat-header-cell  *matHeaderCellDef mat-sort-header>
      <mat-form-field >
        <mat-label>Search Description</mat-label>
        <input matInput 
               [formControl]="descriptionFilter" 
               (click)="$event.stopPropagation()">
        <button mat-button 
                *ngIf="descriptionFilter.value" 
                matSuffix mat-icon-button 
                aria-label="Clear" 
                (click)="descriptionFilter.setValue('')">
          <mat-icon>close</mat-icon>
        </button>
      </mat-form-field>
    </th>

    <td mat-cell *matCellDef="let assessment">
      assessment?.description </td>
  </ng-container>

【讨论】:

为什么不使用&lt;input type="search"&gt; 而不是输入和按钮? 我没有看到 type="search" 的关闭按钮,看起来像是一个有角度的材料,请参阅github.com/angular/components/issues/13315,我从 Angular 的示例页面获得了清除按钮的代码材料输入,material.angular.io/components/input/examples【参考方案5】:

您必须覆盖数据源的 filterPredicate。

您想指定过滤器应用于数据中的哪些属性:-

this.dataSource.filterPredicate = function(data, filter: string): boolean 
    return data.name.toLowerCase().includes(data.symbol.toLowerCase().includes(filter) || data.position.toString().includes(filter);
;

【讨论】:

【参考方案6】:

如果您正在寻找一个范围谓词来过滤掉一个属性上的一系列值:

applyRangePredicate() 
  this.datasource.filterPredicate = (data:
    id: string, filter: string) => 
      let searchlist = JSON.parse(filter);
      var found = false
      searchlist.forEach(item => 
        if (data.id.indexOf(item) !== -1)
          found = true 
      )
      return found
    
  

然后分配一个 json 字符串以将过滤后的数据流式传输到 UI

this.applyRangePredicate()    
this.datasource.filter = JSON.stringify(string[])

【讨论】:

【参考方案7】:

您可以按动态列进行过滤,如没有硬编码的列名,执行以下操作:

// On input focus: setup filterPredicate to only filter by input column
setupFilter(column: string) 
  this.dataSource.filterPredicate = (d: TableDataSourceType, filter: string) => 
    const textToSearch = d[column] && d[column].toLowerCase() || '';
    return textToSearch.indexOf(filter) !== -1;
  ;


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

在模板中你可以有这样的东西:

<ng-container matColumnDef="item-filter">
  <th mat-header-cell *matHeaderCellDef>
    <input (keyup)="applyFilter($event.target.value)" (focus)="setupFilter('name')" />
  </th>
</ng-container>

或者更复杂的例子,动态创建带有逐列过滤的标题行:

<table mat-table [dataSource]="dataSource">
   <ng-container *ngFor="let filterCol of ['names', 'age', 'address']">
     <ng-container matColumnDef="filterCol">
       <th mat-header-cell *matHeaderCellDef>
         <input (keyup)="applyFilter($event.target.value)" (focus)="setupFilter(filterCol)"/>
       </th>
     </ng-container>
   </ng-container>

   <tr mat-header-row *matHeaderRowDef="['names', 'age', 'address']"></tr>
</table>

请注意,您不能拥有多个具有相同键的标题行,因此这不起作用:

<tr mat-header-row *matHeaderRowDef="['names', 'age', 'address']"></tr>
<tr mat-header-row *matHeaderRowDef="['names', 'age', 'address']"></tr>

【讨论】:

效果很好。是否可以一次过滤几列?现在,一旦您按另一列过滤,结果总是会重置。如果您可以在第 1 列中过滤,然后在第 5 列中过滤这些结果,在第 31 列中过滤这些组合结果等等,那就太棒了。可以说是动态组合过滤器。 这实际上是我要找的,谢谢!我想添加 .toString().trim() 很好。 .. 我遇到了一个问题,其中一个表数据是数字【参考方案8】:

我设法做到了:

this.dataSource.filterPredicate = (data, filter) =>
      (data.name.indexOf(filter) !== -1 ||
        data.id.indexOf(filter) !== -1 );
  

【讨论】:

***.com/questions/50264911/… 可能还需要在过滤器输入和要匹配的值上应用 trim() 和 toLowerCase()。这将删除任何空格并忽略大小写的任何变化。 this.dataSource.filterPredicate = (data, filter) =&gt;(data.name.trim().toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1);【参考方案9】:

只需在您的组件中使用以下声明声明一个函数,然后将其分配给 DataSource.filterPredicate。要使用过滤器,只需为 DataSource.filter 属性分配一个字符串。

  customFilter(Data: T, Filter: string): boolean 
    return <true if Data matches filter>
  

【讨论】:

谢谢!这对我来说真的很有用。但是我还是做不到,这就是我做的 this.dataSource.filterPredicate = (data: userData, filter: string) => data.email.indexOf(filterValue) != -1;我现在如何过滤? 更改为 this.dataSource.filterPredicate = (data: userData, filter: string) => data.email.indexOf(filter) != -1 然后使用 this.dataSource.filter 应用过滤器= 过滤器值 ***.com/questions/50264911/… @EduardoMauro 有没有办法做这样的事情:customFilter(Data: T, Filter: string[]) : boolean return boolean ?? @LoganWlv 我认为这是不可能的。您想在 customFilter 中使用一个字符串数组,但 dataSource 属性“filter”是一个字符串。查看文档:material.angular.io/components/table/api

以上是关于在角度 5 中过滤 Angular Material 表中的特定列 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

以角度将列标题过滤器保存在 ag-grid 中

在 Angular 指令中创建过滤器

没有 ng-repeat 的角度过滤器列表

如何正确过滤角度数组

如何使用卡片而不是角度 8 中的数据表过滤数据?

Angular ui-select 仅过滤一个字段