Skip to content

Commit d47b37a

Browse files
andrewseguinmmalerba
authored andcommitted
fix(table): broaden abstraction for filtering (#8059)
* fix(table): broaden abstraction for filtering * cleanup * rename filter function * fix wording
1 parent b2dd17a commit d47b37a

File tree

3 files changed

+32
-19
lines changed

3 files changed

+32
-19
lines changed

src/demo-app/table/table-demo.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ export class TableDemo {
6060
default: return '';
6161
}
6262
};
63-
this.matTableDataSource.filterTermAccessor = (data: UserData) => data.name;
63+
this.matTableDataSource.filterPredicate =
64+
(data: UserData, filter: string) => data.name.indexOf(filter) != -1;
6465
this.filter.valueChanges.subscribe(filter => this.matTableDataSource!.filter = filter);
6566
}
6667

src/lib/table/table-data-source.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class MatTableDataSource<T> implements DataSource<T> {
4444

4545
/**
4646
* Filter term that should be used to filter out objects from the data array. To override how
47-
* the filter matches data objects, provide a custom function on filterTermAccessor.
47+
* data objects match to this filter string, provide a custom function for filterPredicate.
4848
*/
4949
set filter(filter: string) { this._filter.next(filter); }
5050
get filter(): string { return this._filter.value; }
@@ -91,14 +91,24 @@ export class MatTableDataSource<T> implements DataSource<T> {
9191
}
9292

9393
/**
94-
* Transforms data objects into a filter term that will be used to check against the filter if
95-
* a filter is set. By default, the function will iterate over the values of the data object
96-
* and convert them to a lowercase string.
97-
* @param data Data object to convert to a string that checked for containing the filter term.
94+
* Checks if a data object matches the data source's filter string. By default, each data object
95+
* is converted to a string of its properties and returns true if the filter has
96+
* at least one occurrence in that string. By default, the filter string has its whitespace
97+
* trimmed and the match is case-insensitive. May be overriden for a custom implementation of
98+
* filter matching.
99+
* @param data Data object used to check against the filter.
100+
* @param filter Filter string that has been set on the data source.
101+
* @returns Whether the filter matches against the data
98102
*/
99-
filterTermAccessor: ((data: T) => string) = (data: T): string => {
103+
filterPredicate: ((data: T, filter: string) => boolean) = (data: T, filter: string): boolean => {
104+
// Transform the data into a lowercase string of all property values.
100105
const accumulator = (currentTerm, key) => currentTerm + data[key];
101-
return Object.keys(data).reduce(accumulator, '').toLowerCase();
106+
const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
107+
108+
// Transform the filter by converting it to lowercase and removing whitespace.
109+
const transformedFilter = filter.trim().toLowerCase();
110+
111+
return dataStr.indexOf(transformedFilter) != -1;
102112
}
103113

104114
constructor(initialData: T[] = []) {
@@ -145,9 +155,8 @@ export class MatTableDataSource<T> implements DataSource<T> {
145155
// If there is a filter string, filter out data that does not contain it.
146156
// Each data object is converted to a string using the function defined by filterTermAccessor.
147157
// May be overriden for customization.
148-
const filteredData = !this.filter ? data : data.filter(obj => {
149-
return this.filterTermAccessor(obj).indexOf(this.filter) != -1;
150-
});
158+
const filteredData =
159+
!this.filter ? data : data.filter(obj => this.filterPredicate(obj, this.filter));
151160

152161
if (this.paginator) { this._updatePaginator(filteredData.length); }
153162

src/lib/table/table.spec.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ describe('MatTable', () => {
109109
flushMicrotasks(); // Resolve promise that updates paginator's length
110110
expect(dataSource.paginator!.length).toBe(1);
111111

112-
// Change filter to a_2, should match one row
113-
dataSource.filter = 'a_2';
112+
// Change filter to ' A_2 ', should match one row (ignores case and whitespace)
113+
dataSource.filter = ' A_2 ';
114114
fixture.detectChanges();
115115
expectTableToMatchContent(tableElement, [
116116
['Column A', 'Column B', 'Column C'],
@@ -127,14 +127,17 @@ describe('MatTable', () => {
127127
['a_3', 'b_3', 'c_3'],
128128
]);
129129

130-
// Change filter function and filter, should match to rows.
131-
dataSource.filterTermAccessor = data => {
130+
// Change filter function and filter, should match to rows with zebra.
131+
dataSource.filterPredicate = (data, filter) => {
132+
let dataStr;
132133
switch (data.a) {
133-
case 'a_1': return 'elephant';
134-
case 'a_2': return 'zebra';
135-
case 'a_3': return 'monkey';
136-
default: return '';
134+
case 'a_1': dataStr = 'elephant'; break;
135+
case 'a_2': dataStr = 'zebra'; break;
136+
case 'a_3': dataStr = 'monkey'; break;
137+
default: dataStr = '';
137138
}
139+
140+
return dataStr.indexOf(filter) != -1;
138141
};
139142
dataSource.filter = 'zebra';
140143
fixture.detectChanges();

0 commit comments

Comments
 (0)