以角度5

时间:2018-01-16 07:54:21

标签: angular angular-material

在Angular资料官方网站上提到filterPredicate:((data:T,filter:string)=> boolean)将根据特定字段过滤数据。但是没有得到如何开始。

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

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

9 个答案:

答案 0 :(得分:11)

我设法这样做了:

{{1}}

答案 1 :(得分:8)

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

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

答案 2 :(得分:6)

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

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

In [32]: %timeit np.frombuffer(x.tobytes(), dtype='S16')
2.8 µs ± 318 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [33]: %timeit np.fromiter((row.tobytes() for row in x), dtype='S16')
614 µs ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

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

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

};

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

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

}

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

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

}

答案 3 :(得分:1)

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

// 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>

答案 4 :(得分:0)

如果您要查找范围谓词以过滤一个属性的值范围:

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[])

答案 5 :(得分:0)

您必须重写dataSource的filterPredicate。

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

SELECT q.firstname, q.surname, q.dob, p1.personid, m.membershipid 
FROM
(SELECT
  p.firstname,p.surname,p.dob, count(*) as cnt
FROM
  person p
GROUP BY
  p.firstname,p.surname,p.dob
HAVING COUNT(1) > 1) as q
INNER JOIN person p1 ON q.firstname=p1.firstname AND q.surname=p1.surname AND q.dob=p1.dob
INNER JOIN person_membership pm ON p1.personid=pm.personid
INNER JOIN membership m ON pm.memberid = m.membershipid
WHERE pm.personstatus = 'A' AND m.memstatus = 'A'

答案 6 :(得分:0)

要在Naresh's answer上进行扩展,以下HTML代码段显示了如何在同一列中进行排序和过滤,以及如何使用小“ 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>

答案 7 :(得分:0)

使用 filterPredicate 使用 customFilter()

覆盖过滤器逻辑

演示Link

来源Link

enter image description here

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

答案 8 :(得分:0)

这对我有帮助:

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

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

例如。 foundThisField : number = []

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

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