diff --git a/src/material-experimental/mdc-table/table.spec.ts b/src/material-experimental/mdc-table/table.spec.ts index 08d9f00adcee..471562196177 100644 --- a/src/material-experimental/mdc-table/table.spec.ts +++ b/src/material-experimental/mdc-table/table.spec.ts @@ -591,6 +591,45 @@ describe('MDC-based MatTable', () => { ['Footer A', 'Footer B', 'Footer C'], ]); }); + + it('should fall back to empty table if invalid data is passed in', () => { + component.underlyingDataSource.addData(); + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['a_1', 'b_1', 'c_1'], + ['a_2', 'b_2', 'c_2'], + ['a_3', 'b_3', 'c_3'], + ['a_4', 'b_4', 'c_4'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + dataSource.data = null!; + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + component.underlyingDataSource.addData(); + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['a_1', 'b_1', 'c_1'], + ['a_2', 'b_2', 'c_2'], + ['a_3', 'b_3', 'c_3'], + ['a_4', 'b_4', 'c_4'], + ['a_5', 'b_5', 'c_5'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + dataSource.data = {} as any; + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + }); }); }); diff --git a/src/material/table/table-data-source.ts b/src/material/table/table-data-source.ts index 22d01b86e661..119968bab0ac 100644 --- a/src/material/table/table-data-source.ts +++ b/src/material/table/table-data-source.ts @@ -85,6 +85,7 @@ export class _MatTableDataSource< return this._data.value; } set data(data: T[]) { + data = Array.isArray(data) ? data : []; this._data.next(data); // Normally the `filteredData` is updated by the re-render // subscription, but that won't happen if it's inactive. diff --git a/src/material/table/table.spec.ts b/src/material/table/table.spec.ts index e47337e73a68..0b5d0cb14069 100644 --- a/src/material/table/table.spec.ts +++ b/src/material/table/table.spec.ts @@ -576,6 +576,45 @@ describe('MatTable', () => { ['Footer A', 'Footer B', 'Footer C'], ]); }); + + it('should fall back to empty table if invalid data is passed in', () => { + component.underlyingDataSource.addData(); + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['a_1', 'b_1', 'c_1'], + ['a_2', 'b_2', 'c_2'], + ['a_3', 'b_3', 'c_3'], + ['a_4', 'b_4', 'c_4'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + dataSource.data = null!; + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + component.underlyingDataSource.addData(); + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['a_1', 'b_1', 'c_1'], + ['a_2', 'b_2', 'c_2'], + ['a_3', 'b_3', 'c_3'], + ['a_4', 'b_4', 'c_4'], + ['a_5', 'b_5', 'c_5'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + + dataSource.data = {} as any; + fixture.detectChanges(); + expectTableToMatchContent(tableElement, [ + ['Column A', 'Column B', 'Column C'], + ['Footer A', 'Footer B', 'Footer C'], + ]); + }); }); });