From 2a3599e331bdaa8221a1c4a074c69da10b2600e9 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 19 Oct 2018 17:08:00 +0200 Subject: [PATCH] fix(table): delimit words when filtering (#13487) --- src/lib/table/table-data-source.ts | 12 +++++++++--- src/lib/table/table.spec.ts | 12 ++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/lib/table/table-data-source.ts b/src/lib/table/table-data-source.ts index d04f7248603..976420fa32d 100644 --- a/src/lib/table/table-data-source.ts +++ b/src/lib/table/table-data-source.ts @@ -173,9 +173,15 @@ export class MatTableDataSource extends DataSource { */ filterPredicate: ((data: T, filter: string) => boolean) = (data: T, filter: string): boolean => { // Transform the data into a lowercase string of all property values. - const accumulator = - (currentTerm: string, key: string) => currentTerm + (data as {[key: string]: any})[key]; - const dataStr = Object.keys(data).reduce(accumulator, '').toLowerCase(); + const dataStr = Object.keys(data).reduce((currentTerm: string, key: string) => { + // Use an obscure Unicode character to delimit the words in the concatenated string. + // This avoids matches where the values of two columns combined will match the user's query + // (e.g. `Flute` and `Stop` will match `Test`). The character is intended to be something + // that has a very low chance of being typed in by somebody in a text field. This one in + // particular is "White up-pointing triangle with dot" from + // https://en.wikipedia.org/wiki/List_of_Unicode_characters + return currentTerm + (data as {[key: string]: any})[key] + '◬'; + }, '').toLowerCase(); // Transform the filter by converting it to lowercase and removing whitespace. const transformedFilter = filter.trim().toLowerCase(); diff --git a/src/lib/table/table.spec.ts b/src/lib/table/table.spec.ts index d8a8c8b0c08..b6fd1ebbf6b 100644 --- a/src/lib/table/table.spec.ts +++ b/src/lib/table/table.spec.ts @@ -259,6 +259,18 @@ describe('MatTable', () => { ]); })); + it('should not match concatenated words', fakeAsync(() => { + // Set the value to the last character of the first + // column plus the first character of the second column. + dataSource.filter = '1b'; + fixture.detectChanges(); + expect(dataSource.filteredData.length).toBe(0); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + })); + it('should be able to sort the table contents', () => { // Activate column A sort component.sort.sort(component.sortHeader);