I have angular 4 project with material 2, I want to filter the data in MatTable. DataSource filter is working fine when we filter data on field which are not nested.
this.dataSource = new MatTableDataSource([
{ orderNumber: 1, orderInfo: { type: 'ABC'}, date: '12/3/2012 9:42:39 AM'},
{ orderNumber: 3, orderInfo: { type: 'Hello' }, date: '12/2/2018 9:42:39 AM'},
]);
Filter is working fine for orderNumber, date but not working properly with type field in orderInfo object.
DataSource has filterPredicate()
method that needs to override in our application as follows. Add this code in your component after data source initialization.
this.dataSource.filterPredicate = (data, filter: string) => {
const accumulator = (currentTerm, key) => {
return key === 'orderInfo' ? currentTerm + data.orderInfo.type : currentTerm + data[key];
};
const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
// Transform the filter by converting it to lowercase and removing whitespace.
const transformedFilter = filter.trim().toLowerCase();
return dataStr.indexOf(transformedFilter) !== -1;
};
Here is a solution that incorporates recursion so you don't have to hard code each nested object or their key/value pairs.
this.dataSource.filterPredicate = (data, filter: string) => {
const accumulator = (currentTerm, key) => {
return this.nestedFilterCheck(currentTerm, data, key);
};
const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
// Transform the filter by converting it to lowercase and removing whitespace.
const transformedFilter = filter.trim().toLowerCase();
return dataStr.indexOf(transformedFilter) !== -1;
};
And the nestedFilterCheck
nestedFilterCheck(search, data, key) {
if (typeof data[key] === 'object') {
for (const k in data[key]) {
if (data[key][k] !== null) {
search = this.nestedFilterCheck(search, data[key], k);
}
}
} else {
search += data[key];
}
return search;
}
Thanks to @Sagar Kharche for the filterPredicate
override.
This is a very generic solution and will work for sure. It does not depends on the structure of json, be it simple or nested, this solution works for all.
this.dataSource.filterPredicate = (data: any, filter) => {
const dataStr =JSON.stringify(data).toLowerCase();
return dataStr.indexOf(filter) != -1;
}
来源:https://stackoverflow.com/questions/49833315/angular-material-2-datasource-filter-with-nested-object