在角度 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>
【讨论】:
为什么不使用<input type="search">
而不是输入和按钮?
我没有看到 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) =>
(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 表中的特定列 [重复]的主要内容,如果未能解决你的问题,请参考以下文章