Skip to content

Commit 9fa7f08

Browse files
committed
feat(table): enable multiple data rows
1 parent 2e54f13 commit 9fa7f08

File tree

13 files changed

+432
-53
lines changed

13 files changed

+432
-53
lines changed

src/cdk/table/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ ng_module(
99
module_name = "@angular/cdk/table",
1010
deps = [
1111
"//src/cdk/collections",
12+
"//src/cdk/coercion",
1213
"@rxjs",
1314
],
1415
tsconfig = "//src/cdk:tsconfig-build.json",

src/cdk/table/row.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ export interface CdkCellOutletRowContext<T> {
136136
$implicit?: T;
137137

138138
/** Index location of the row that this cell is located within. */
139+
rowIndex?: number;
140+
141+
/** Index of the data object in the provided data array. */
139142
index?: number;
140143

141144
/** Length of the number of total rows. */

src/cdk/table/table-errors.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ export function getTableMultipleDefaultRowDefsError() {
3535
* Returns an error to be thrown when there are no matching row defs for a particular set of data.
3636
* @docs-private
3737
*/
38-
export function getTableMissingMatchingRowDefError() {
39-
return Error(`Could not find a matching row definition for the provided row data.`);
38+
export function getTableMissingMatchingRowDefError(data: any) {
39+
return Error(`Could not find a matching row definition for the` +
40+
`provided row data: ${JSON.stringify(data)}`);
4041
}
4142

4243
/**

src/cdk/table/table.spec.ts

Lines changed: 66 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -524,23 +524,61 @@ describe('CdkTable', () => {
524524

525525
it('should error if there is row data that does not have a matching row template',
526526
fakeAsync(() => {
527+
const whenRowWithoutDefaultFixture = createComponent(WhenRowWithoutDefaultCdkTableApp);
528+
const data = whenRowWithoutDefaultFixture.componentInstance.dataSource.data;
527529
expect(() => {
528530
try {
529-
createComponent(WhenRowWithoutDefaultCdkTableApp).detectChanges();
531+
whenRowWithoutDefaultFixture.detectChanges();
530532
flush();
531533
} catch {
532534
flush();
533535
}
534-
}).toThrowError(getTableMissingMatchingRowDefError().message);
536+
}).toThrowError(getTableMissingMatchingRowDefError(data[0]).message);
535537
}));
536538

537-
it('should error if there are multiple rows that do not have a when function', fakeAsync(() => {
539+
it('should fail when multiple rows match data without enableRowMultiplex', fakeAsync(() => {
538540
let whenFixture = createComponent(WhenRowMultipleDefaultsCdkTableApp);
539541
expect(() => {
540542
whenFixture.detectChanges();
541543
flush();
542544
}).toThrowError(getTableMultipleDefaultRowDefsError().message);
543545
}));
546+
547+
describe('with enableRowMultiplex', () => {
548+
it('should be able to render multiple rows per data object', () => {
549+
let whenFixture = createComponent(WhenRowCdkTableApp);
550+
whenFixture.componentInstance.enableRowMultiplex = true;
551+
whenFixture.detectChanges();
552+
553+
const data = whenFixture.componentInstance.dataSource.data;
554+
expectTableToMatchContent(whenFixture.nativeElement.querySelector('cdk-table'), [
555+
['Column A', 'Column B', 'Column C'],
556+
[data[0].a, data[0].b, data[0].c],
557+
[data[1].a, data[1].b, data[1].c],
558+
['index_1_special_row'],
559+
[data[2].a, data[2].b, data[2].c],
560+
['c3_special_row'],
561+
[data[3].a, data[3].b, data[3].c],
562+
]);
563+
});
564+
565+
it('should have the correct data and row indicies', () => {
566+
let whenFixture = createComponent(WhenRowCdkTableApp);
567+
whenFixture.componentInstance.enableRowMultiplex = true;
568+
whenFixture.componentInstance.showIndexColumns();
569+
whenFixture.detectChanges();
570+
571+
expectTableToMatchContent(whenFixture.nativeElement.querySelector('cdk-table'), [
572+
['Data Index', 'Row Index'],
573+
['0', '0'],
574+
['1', '1'],
575+
['1', '2'],
576+
['2', '3'],
577+
['2', '4'],
578+
['3', '5'],
579+
]);
580+
});
581+
});
544582
});
545583

546584
describe('with trackBy', () => {
@@ -923,7 +961,7 @@ class BooleanRowCdkTableApp {
923961

924962
@Component({
925963
template: `
926-
<cdk-table [dataSource]="dataSource">
964+
<cdk-table [dataSource]="dataSource" [enableRowMultiplex]="enableRowMultiplex">
927965
<ng-container cdkColumnDef="column_a">
928966
<cdk-header-cell *cdkHeaderCellDef> Column A</cdk-header-cell>
929967
<cdk-cell *cdkCellDef="let row"> {{row.a}}</cdk-cell>
@@ -941,30 +979,50 @@ class BooleanRowCdkTableApp {
941979
942980
<ng-container cdkColumnDef="index1Column">
943981
<cdk-header-cell *cdkHeaderCellDef> Column C</cdk-header-cell>
944-
<cdk-cell *cdkCellDef="let row"> index_1_special_row </cdk-cell>
982+
<cdk-cell *cdkCellDef="let row"> index_1_special_row</cdk-cell>
945983
</ng-container>
946984
947985
<ng-container cdkColumnDef="c3Column">
948986
<cdk-header-cell *cdkHeaderCellDef> Column C</cdk-header-cell>
949-
<cdk-cell *cdkCellDef="let row"> c3_special_row </cdk-cell>
987+
<cdk-cell *cdkCellDef="let row"> c3_special_row</cdk-cell>
988+
</ng-container>
989+
990+
<ng-container cdkColumnDef="dataIndex">
991+
<cdk-header-cell *cdkHeaderCellDef> Data Index</cdk-header-cell>
992+
<cdk-cell *cdkCellDef="let row; let index = index"> {{index}}</cdk-cell>
993+
</ng-container>
994+
995+
<ng-container cdkColumnDef="rowIndex">
996+
<cdk-header-cell *cdkHeaderCellDef> Row Index</cdk-header-cell>
997+
<cdk-cell *cdkCellDef="let row; let rowIndex = rowIndex"> {{rowIndex}}</cdk-cell>
950998
</ng-container>
951999
9521000
<cdk-header-row *cdkHeaderRowDef="columnsToRender"></cdk-header-row>
9531001
<cdk-row *cdkRowDef="let row; columns: columnsToRender"></cdk-row>
954-
<cdk-row *cdkRowDef="let row; columns: ['index1Column']; when: isIndex1"></cdk-row>
955-
<cdk-row *cdkRowDef="let row; columns: ['c3Column']; when: hasC3"></cdk-row>
1002+
<cdk-row *cdkRowDef="let row; columns: isIndex1Columns; when: isIndex1"></cdk-row>
1003+
<cdk-row *cdkRowDef="let row; columns: hasC3Columns; when: hasC3"></cdk-row>
9561004
</cdk-table>
9571005
`
9581006
})
9591007
class WhenRowCdkTableApp {
1008+
enableRowMultiplex = false;
9601009
dataSource: FakeDataSource = new FakeDataSource();
9611010
columnsToRender = ['column_a', 'column_b', 'column_c'];
1011+
isIndex1Columns = ['index1Column'];
1012+
hasC3Columns = ['c3Column'];
9621013
isIndex1 = (index: number, _rowData: TestData) => index == 1;
9631014
hasC3 = (_index: number, rowData: TestData) => rowData.c == 'c_3';
9641015

9651016
constructor() { this.dataSource.addData(); }
9661017

9671018
@ViewChild(CdkTable) table: CdkTable<TestData>;
1019+
1020+
showIndexColumns() {
1021+
const indexColumns = ['dataIndex', 'rowIndex'];
1022+
this.columnsToRender = indexColumns;
1023+
this.isIndex1Columns = indexColumns;
1024+
this.hasC3Columns = indexColumns;
1025+
}
9681026
}
9691027

9701028
@Component({

0 commit comments

Comments
 (0)