【问题标题】:Filtering specific column in Angular Material table in angular 5 [duplicate]在角度 5 中过滤 Angular Material 表中的特定列 [重复]
【发布时间】: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 的单个属性进行搜索。

【问题讨论】:

    标签: angular angular-material


    【解决方案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>
        

        【讨论】:

        【解决方案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 );
              }
            

            【讨论】:

            • 可能还需要在过滤器输入和要匹配的值上应用 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 应用过滤器= 过滤器值
            • @EduardoMauro 有没有办法做这样的事情:customFilter(Data: T, Filter: string[]) : boolean { return boolean } ??
            • @LoganWlv 我认为这是不可能的。您想在 customFilter 中使用一个字符串数组,但 dataSource 属性“filter”是一个字符串。查看文档:material.angular.io/components/table/api
            猜你喜欢
            • 2018-10-01
            • 2020-08-21
            • 2019-12-12
            • 2018-08-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多