Skip to content

Commit 1d87b4c

Browse files
crisbetojosephperrott
authored andcommitted
fix(table): delimit words when filtering (#13487)
1 parent 244111b commit 1d87b4c

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,15 @@ export class MatTableDataSource<T> extends DataSource<T> {
173173
*/
174174
filterPredicate: ((data: T, filter: string) => boolean) = (data: T, filter: string): boolean => {
175175
// Transform the data into a lowercase string of all property values.
176-
const accumulator =
177-
(currentTerm: string, key: string) => currentTerm + (data as {[key: string]: any})[key];
178-
const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase();
176+
const dataStr = Object.keys(data).reduce((currentTerm: string, key: string) => {
177+
// Use an obscure Unicode character to delimit the words in the concatenated string.
178+
// This avoids matches where the values of two columns combined will match the user's query
179+
// (e.g. `Flute` and `Stop` will match `Test`). The character is intended to be something
180+
// that has a very low chance of being typed in by somebody in a text field. This one in
181+
// particular is "White up-pointing triangle with dot" from
182+
// https://en.wikipedia.org/wiki/List_of_Unicode_characters
183+
return currentTerm + (data as {[key: string]: any})[key] + '◬';
184+
}, '').toLowerCase();
179185

180186
// Transform the filter by converting it to lowercase and removing whitespace.
181187
const transformedFilter = filter.trim().toLowerCase();

src/lib/table/table.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ describe('MatTable', () => {
259259
]);
260260
}));
261261

262+
it('should not match concatenated words', fakeAsync(() => {
263+
// Set the value to the last character of the first
264+
// column plus the first character of the second column.
265+
dataSource.filter = '1b';
266+
fixture.detectChanges();
267+
expect(dataSource.filteredData.length).toBe(0);
268+
expectTableToMatchContent(tableElement, [
269+
['Column A', 'Column B', 'Column C'],
270+
['Footer A', 'Footer B', 'Footer C'],
271+
]);
272+
}));
273+
262274
it('should be able to sort the table contents', () => {
263275
// Activate column A sort
264276
component.sort.sort(component.sortHeader);

0 commit comments

Comments
 (0)