I have an Angular MatTableDataSource object with a number of top-level properties and a nested array property that contains a list of IDs that are relevant to that row.
Each entry in the MatTableDataSource array looks something like this:
IMSI: 505230000000006,
isActive: "Yes",
APNList: [1,2,3,4,5]
I also have a multi mat-select element from which I can select one or more of the IDs that relate to the entries in the APNList nested array.
I need to create a filter on the selectionChange event of the multiselect that will filter the MatTableDataSource by matching the array returned by the mat-select with the nested array in each entry.
So, for example, selecting 1 and 2 in the select will filter the MatTableDataSource to only entries that have 1 and/or 2 in its APNList array.
I feel like some combination of filterPredicate and ES6 some() will get the job done, but haven't quite gotten my head around how to achieve it.
Any help would be greatly appreciated!
CodePudding user response:
You have two options, I'll start by making a random data source.
type entry = {
IMSI: number;
isActive: string;
APNList: number[];
};
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {
dataSource: MatTableDataSource<entry> = new MatTableDataSource([
{ IMSI: 505230000000006, isActive: 'Yes', APNList: [1, 2, 3, 4, 5] },
{ IMSI: 505230000000007, isActive: 'Yes', APNList: [6, 7, 8, 9, 10] },
{ IMSI: 505230000000008, isActive: 'Yes', APNList: [1, 2, 3, 4, 5] },
]);
...
I'll hard code the check for 1 and 2 for simplicity, obviously your functions would have parameters to allow for different searches.
Option 1: Filter the data array directly using filter()
option1() {
const data: entry[] = this.dataSource.data;
const filteredData: entry[] = data.filter(
(entry) => entry.APNList.includes(1) || entry.APNList.includes(2)
);
console.log(filteredData);
}
filter() has a function as a parameter, the function needs to return true for the element to pass through the filter.
Option 2: Filter the data array indirectly using the MatTableDataSource class
option2() {
this.dataSource.filterPredicate = (entry: entry, filter: string) =>
entry.APNList.includes(1) || entry.APNList.includes(2);
//Data is only filtered after updating the filter string
this.dataSource.filter = 'Some filter string';
console.log('Option2: ', this.dataSource.filteredData);
}
We can provide a custom filter function as the filterPredicate property, the same as with filter(). However, this function has a second string parameter which corresponds to the filter property of the MatTableDataSource class. You are meant to use this filter string to filter your data.
The filtered data appears in the filteredData property of the class. Keep in mind, filteredData only updates when the filter property changes. Also, if the filter property is empty, filteredData will contain all data, regardless of the function. More info in the docs: https://material.angular.io/components/table/api#MatTableDataSource
Stackblitz: https://stackblitz.com/edit/angular-ivy-zamkgj?file=src/app/test/test.component.ts
