Filtering specific column in Angular Material Table with filtering in angular?
Adding to bugs' answer. Here's a more elaborate implementation,
export class FilterTable implements AfterViewInit {
//some datasource
datasource //=
displayedColumns //=insert column names on which you want to filter whether they are displayed or not, but present in the datasource
// Apply filter to the datasource
applyFilter(filterValue: string) {
this.datasource.filter = filterValue;
}
ngAfterViewInit() {
// Overwriting filterPredicate here, as it needs to be done after the datasource is loaded.
this.datasource.filterPredicate = (data, filter) => {
var tot = false;
for (let column of this.displayedColumns) {
//incase if there is a date type and is displayed differently using a pipe, then convert it intorequired format before filtering
//check if all the columnson which you are filtering are actually present
if ((column in data) && (new Date(data[column].toString()).toString() == "Invalid Date")) {
//if not date column
tot = (tot || data[column].toString().trim().toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1);
} else {
//change this to the format in which date is displayed
var date = new Date(data[column].toString());
var m = date.toDateString().slice(4, 7) + " " + date.getDate() + " " + date.getFullYear();
tot = (tot || m.toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1);
}
}
return tot;
}
}
}
Please feel free to suggest edits, if this could be improved
Material has implemented its own search feature you can override it by updating the filterPredicate property on the date source. Call the generateTable function on ngOninit() life cycle.
generateTable(tableData: any) {
this.dataSource = new MatTableDataSource(tableData);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.dataSource.filterPredicate = (data: any, filter: string) => {
console.log(data);
console.log(filter);
let matchFound = false;
for (let column of this.displayedColumns) {
if(column in data) {
if(data[column]) {
matchFound = (matchFound || data[column].toString().trim().toLowerCase().indexOf(filter.trim().toLowerCase()) !== -1)
}
}
}
return matchFound;
}
}
Whenever you wish to apply the filter, update the filter property on dataSource to the string value to be searched.
applyFilter(searchValue: any) {
this.dataSource.filter = this.filterText.trim().toLowerCase();
}
You have to override the filterPredicate
of your dataSource.
Here's an example of how to do it: Working demo
Essentially, you want to specify what properties in your data the filter is applied to:
this.dataSource.filterPredicate = function(data, filter: string): boolean {
return data.name.toLowerCase().includes(filter) || data.symbol.toLowerCase().includes(filter) || data.position.toString().includes(filter);
};
In Angular Material Tables, we can create column based filters from data itself.
Source Link
Demo Link
For that, we need to override the filterPredicate method with customFilter() method
...
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
}
Check complete working code here