Skip to content

Commit d29cc04

Browse files
committed
refactor(material/table): add filterPredicate non-object warning
1 parent da68c8b commit d29cc04

File tree

2 files changed

+54
-7
lines changed

2 files changed

+54
-7
lines changed

src/material/table/table-data-source.spec.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
import {MatTableDataSource} from './table-data-source';
2-
import {ComponentFixture, TestBed} from '@angular/core/testing';
2+
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
33
import {MatSort, MatSortModule} from '@angular/material/sort';
44
import {Component, ViewChild} from '@angular/core';
55

6+
declare global {
7+
interface Window {
8+
ngDevMode?: object | null;
9+
}
10+
}
11+
612
describe('MatTableDataSource', () => {
713
describe('sort', () => {
8-
let dataSource: MatTableDataSource<any>;
14+
let dataSource: MatTableDataSource<{'prop': string | number}>;
915
let fixture: ComponentFixture<MatSortApp>;
1016
let sort: MatSort;
1117

@@ -18,7 +24,7 @@ describe('MatTableDataSource', () => {
1824
});
1925

2026
/** Test the data source's `sortData` function. */
21-
function testSortWithValues(values: any[]) {
27+
function testSortWithValues(values: (string | number)[]) {
2228
// The data source and MatSort expect the list to contain objects with values, where
2329
// the sort should be performed over a particular key.
2430
// Map the values into an array of objects where each value is keyed by "prop"
@@ -73,13 +79,45 @@ describe('MatTableDataSource', () => {
7379
});
7480

7581
it('should update filteredData even if the data source is disconnected', () => {
76-
dataSource.data = [1, 2, 3, 4, 5];
77-
expect(dataSource.filteredData).toEqual([1, 2, 3, 4, 5]);
82+
dataSource.data = [{'prop': 1}, {'prop': 2}, {'prop': 3}];
83+
expect(dataSource.filteredData).toEqual([{'prop': 1}, {'prop': 2}, {'prop': 3}]);
7884

7985
dataSource.disconnect();
80-
dataSource.data = [5, 4, 3, 2, 1];
81-
expect(dataSource.filteredData).toEqual([5, 4, 3, 2, 1]);
86+
dataSource.data = [{'prop': 3}, {'prop': 2}, {'prop': 1}];
87+
expect(dataSource.filteredData).toEqual([{'prop': 3}, {'prop': 2}, {'prop': 1}]);
8288
});
89+
90+
it('should filter data', () => {
91+
dataSource.data = [{'prop': 1}, {'prop': 'foo'}, {'prop': 'banana'}];
92+
dataSource.filter = 'b';
93+
expect(dataSource.filteredData).toEqual([{'prop': 'banana'}]);
94+
});
95+
96+
it('does not warn in non-dev mode when filtering non-object data', fakeAsync(() => {
97+
const warnSpy = spyOn(console, 'warn');
98+
window.ngDevMode = null;
99+
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];
100+
101+
dataSource.filter = '1';
102+
tick();
103+
104+
expect(warnSpy).not.toHaveBeenCalled();
105+
expect(dataSource.filteredData).toEqual([]);
106+
}));
107+
108+
it('displays the warning in dev mode when filtering non-object data', fakeAsync(() => {
109+
const warnSpy = spyOn(console, 'warn');
110+
window.ngDevMode = {};
111+
dataSource.data = [1, 2, 3, 4, 5] as unknown as {'prop': number}[];
112+
113+
dataSource.filter = '1';
114+
tick();
115+
116+
expect(warnSpy).toHaveBeenCalledWith(
117+
jasmine.stringContaining('requires data to be a non-null object'),
118+
);
119+
expect(dataSource.filteredData).toEqual([]);
120+
}));
83121
});
84122
});
85123

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,15 @@ export class MatTableDataSource<
233233
* @returns Whether the filter matches against the data
234234
*/
235235
filterPredicate: (data: T, filter: string) => boolean = (data: T, filter: string): boolean => {
236+
if (
237+
(typeof ngDevMode === 'undefined' || ngDevMode) &&
238+
(typeof data !== 'object' || data === null)
239+
) {
240+
console.warn(
241+
'Default implementation of filterPredicate requires data to be a non-null object.',
242+
);
243+
}
244+
236245
// Transform the filter by converting it to lowercase and removing whitespace.
237246
const transformedFilter = filter.trim().toLowerCase();
238247
// Loops over the values in the array and returns true if any of them match the filter string

0 commit comments

Comments
 (0)