I have MatTable
that i want to filter using values
i store from the user input
I am able to check that that the value match the data but I don't know how to filter the table without using filterPredicare
as using another one will get me a duplication problem.
This is my component NgOnInit
:
ngOnInit() {
this.marinService.getAllContainers().subscribe((result) => {
//Data
this.dataSource = new MatTableDataSource(result);
//Paginator
this.dataSource.paginator = this.paginator;
//AutoFilter Form 1st page
this.clientType = this.route.snapshot.queryParamMap.get('clientType');
this.storageType= this.route.snapshot.queryParamMap.get('storageTypes');
console.log('The Client name is : '+this.clientType+' '+'The storage Facility is : '+this.storageType);
this.tableFilter();
//snapShot Filter
//CheckBoxFilter
this.dataSource.filterPredicate = (data: Container, filter: any) => {
return filter.split(',').every((item: any) => data.SOG_MCOLH.indexOf(item)!== -1);
};
this.filterCheckboxes.subscribe((newFilterValue: any[]) => {
this.dataSource.filter = newFilterValue.join(',');
});
});
}
This is my function
:
tableFilter(){
var data : Container = this.dataSource;
var newData: any[];
if(data.LQOCH_SHM_LOEZI_QTSR = this.clientType){
console.log(data.LQOCH_SHM_LOEZI_QTSR);
}else{
console.log("Hi Not working")
return this.dataSource;
}
}
I have tried using the same "filtering method" as i used in the filterPrediacte
and it didn't work out.
In my opinion, it would be better to modify the filterPredicate()
to suit your needs. The mat-table
has been optimized to improve performance so creating your own filter for the table without the use of filterPredicate()
could result in performance issues. I have a working example of this on stackblitz.
In my example, I am creating a filter as an object of the below format
{
columnName: Array(filterValues),
...
}
(since in a checkbox, you can filter through particular columns based on a particular value and there can be multiple filters on the same column)
I am using a function updateFilter()
to modify the filter based on the selected checkbox. This will just add the filter to the filter object if the checkbox is checked and remove it from the filter object once unchecked. This filter object will then be passed to the mat-table
filter as a string (since the filterPredicate()
only accepts string values)
updateFilter(column: string, filter: string) {
if (!this.filterValues.hasOwnProperty(column)) {
this.filterValues[column] = [filter];
} else {
this.filterValues[column].includes(filter) ?
this.filterValues[column] = this.filterValues[column].filter(filterValue => filterValue !== filter) :
this.filterValues[column].push(filter);
}
this.applyFilter();
}
In filterPredicate()
, parse the filter object and filter the data based on this object. I am using the variable conditions
since there can be multiple checkboxes selected at once (we will need to pass all data that satisfies all selected conditions. try selecting all checkboxes in the example). For any custom filter (eg. show all data with progress > 90%), you can add the condition. I have added a custom filter for name since the column contains both first name and last name while I am only filtering based on first name (subset of the name).
this.dataSource.filterPredicate = ((data: UserData, filter: string): boolean => {
const filterValues = JSON.parse(filter);
let conditions = true;
for (let filterKey in filterValues) {
if (filterKey === 'name') {
conditions = conditions && data[filterKey].trim().toLowerCase().indexOf(filterValues[filterKey]) !== -1;
}
else if (filterValues[filterKey].length) {
conditions = conditions && filterValues[filterKey].includes(data[filterKey].trim().toLowerCase());
}
}
return conditions;
});
Finally, in order to trigger the filter. On selecting the checkbox, just call updateFilter()
along with the columnName to filter through and the value. For eg. to show red colors, call updateFilter('color', 'red')
where 'color'
is the column name and 'red'
is the filter value.
Edit: There are different ways you can do what you mentioned in the comments. You could set the value to your checkbox and add a template reference variable. Below #color
is your template reference variable. This allows you to access this checkbox value in your html by using color.value
<mat-checkbox value="blue" (change)="updateFilter('color', color.value)" #color>Show blue colors</mat-checkbox>
If you have the value defined in your component and you are passing it to the checkbox using [value]
. You can either use a template reference variable again to pass the data or just pass the value itself.
component
name: string = 'Amelia';
HTML
// No interpolation required when passing the value to the function.
<mat-checkbox [value]="name" (change)="updateFilter('name', name)">Show all first name - Amelia</mat-checkbox>
Check out the updated stackblitz to see this in action.