I'm using mat-table. It has a filter which works fine with doc example:
From https://material.angular.io/components/table/overview, the original code is:
<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'}
];
With this implementation, when filter, it filter for any column.
Now I'm trying to change the filter because I want is filter just for "name" column, so I'm trying to rewrite the filter and assign to 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;
}
In console, I can see this.dataSource.filteredData has the data I want to print, but table is not reload.
What are I'm missing?
Be aware that all fields of the class displayed in table rows, are subject to filtering, even if you do not display that field as a column.
Any filter for the dataSource of city table, also applies to id column, which generally we do not display to the end user.
I found the solution here.
It's necessary to rewrite
filterPredicate
, and just use it as usual,filterPredicate
needs to returntrue
when filter passes andfalse
when it doesn'tDon't forget to apply
.trim().toLowerCase()
on your data or you may encounter unexpected results. See my example below:when using parent-child componenet (or service with say
observable
) you must always in the component containing theMatTableDataSource
set an"applyFilter"
function (name not matters)in the table component i added
@Input
's for the filter string value as aFormControl
, and sent a filter function (filterfn
)in the init
in parent html
in parent component