Skip to content

Commit 9752b1d

Browse files
crisbetoandrewseguin
authored andcommitted
fix(material/table): better handling of invalid data (#18953)
The table data source is set up to expect an array and will throw a cryptic error down the line if the value is anything different. While typings should be enough to enforce this, if the value comes from somewhere in the view it may not get caught. Since the effort for handling it on our end is minimal, these changes add some logic that fall back to an empty array if the value is invalid. Fixes #18859. (cherry picked from commit e2a0b9e)
1 parent 7be61b6 commit 9752b1d

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

src/material-experimental/mdc-table/table.spec.ts

+39
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,45 @@ describe('MDC-based MatTable', () => {
591591
['Footer A', 'Footer B', 'Footer C'],
592592
]);
593593
});
594+
595+
it('should fall back to empty table if invalid data is passed in', () => {
596+
component.underlyingDataSource.addData();
597+
fixture.detectChanges();
598+
expectTableToMatchContent(tableElement, [
599+
['Column A', 'Column B', 'Column C'],
600+
['a_1', 'b_1', 'c_1'],
601+
['a_2', 'b_2', 'c_2'],
602+
['a_3', 'b_3', 'c_3'],
603+
['a_4', 'b_4', 'c_4'],
604+
['Footer A', 'Footer B', 'Footer C'],
605+
]);
606+
607+
dataSource.data = null!;
608+
fixture.detectChanges();
609+
expectTableToMatchContent(tableElement, [
610+
['Column A', 'Column B', 'Column C'],
611+
['Footer A', 'Footer B', 'Footer C'],
612+
]);
613+
614+
component.underlyingDataSource.addData();
615+
fixture.detectChanges();
616+
expectTableToMatchContent(tableElement, [
617+
['Column A', 'Column B', 'Column C'],
618+
['a_1', 'b_1', 'c_1'],
619+
['a_2', 'b_2', 'c_2'],
620+
['a_3', 'b_3', 'c_3'],
621+
['a_4', 'b_4', 'c_4'],
622+
['a_5', 'b_5', 'c_5'],
623+
['Footer A', 'Footer B', 'Footer C'],
624+
]);
625+
626+
dataSource.data = {} as any;
627+
fixture.detectChanges();
628+
expectTableToMatchContent(tableElement, [
629+
['Column A', 'Column B', 'Column C'],
630+
['Footer A', 'Footer B', 'Footer C'],
631+
]);
632+
});
594633
});
595634
});
596635

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

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export class _MatTableDataSource<
8585
return this._data.value;
8686
}
8787
set data(data: T[]) {
88+
data = Array.isArray(data) ? data : [];
8889
this._data.next(data);
8990
// Normally the `filteredData` is updated by the re-render
9091
// subscription, but that won't happen if it's inactive.

src/material/table/table.spec.ts

+39
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,45 @@ describe('MatTable', () => {
576576
['Footer A', 'Footer B', 'Footer C'],
577577
]);
578578
});
579+
580+
it('should fall back to empty table if invalid data is passed in', () => {
581+
component.underlyingDataSource.addData();
582+
fixture.detectChanges();
583+
expectTableToMatchContent(tableElement, [
584+
['Column A', 'Column B', 'Column C'],
585+
['a_1', 'b_1', 'c_1'],
586+
['a_2', 'b_2', 'c_2'],
587+
['a_3', 'b_3', 'c_3'],
588+
['a_4', 'b_4', 'c_4'],
589+
['Footer A', 'Footer B', 'Footer C'],
590+
]);
591+
592+
dataSource.data = null!;
593+
fixture.detectChanges();
594+
expectTableToMatchContent(tableElement, [
595+
['Column A', 'Column B', 'Column C'],
596+
['Footer A', 'Footer B', 'Footer C'],
597+
]);
598+
599+
component.underlyingDataSource.addData();
600+
fixture.detectChanges();
601+
expectTableToMatchContent(tableElement, [
602+
['Column A', 'Column B', 'Column C'],
603+
['a_1', 'b_1', 'c_1'],
604+
['a_2', 'b_2', 'c_2'],
605+
['a_3', 'b_3', 'c_3'],
606+
['a_4', 'b_4', 'c_4'],
607+
['a_5', 'b_5', 'c_5'],
608+
['Footer A', 'Footer B', 'Footer C'],
609+
]);
610+
611+
dataSource.data = {} as any;
612+
fixture.detectChanges();
613+
expectTableToMatchContent(tableElement, [
614+
['Column A', 'Column B', 'Column C'],
615+
['Footer A', 'Footer B', 'Footer C'],
616+
]);
617+
});
579618
});
580619
});
581620

0 commit comments

Comments
 (0)