@@ -69,11 +69,11 @@ describe('CdkTable', () => {
69
69
} ) ;
70
70
71
71
it ( 'with a rendered header with the right number of header cells' , ( ) => {
72
- const header = getHeaderRow ( tableElement ) ;
72
+ const header = getHeaderRows ( tableElement ) [ 0 ] ;
73
73
74
74
expect ( header ) . toBeTruthy ( ) ;
75
75
expect ( header . classList ) . toContain ( 'customHeaderRowClass' ) ;
76
- expect ( getHeaderCells ( tableElement ) . length ) . toBe ( component . columnsToRender . length ) ;
76
+ expect ( getHeaderCells ( header ) . length ) . toBe ( component . columnsToRender . length ) ;
77
77
} ) ;
78
78
79
79
it ( 'with rendered rows with right number of row cells' , ( ) => {
@@ -87,7 +87,8 @@ describe('CdkTable', () => {
87
87
} ) ;
88
88
89
89
it ( 'with column class names provided to header and data row cells' , ( ) => {
90
- getHeaderCells ( tableElement ) . forEach ( ( headerCell , index ) => {
90
+ const header = getHeaderRows ( tableElement ) [ 0 ] ;
91
+ getHeaderCells ( header ) . forEach ( ( headerCell , index ) => {
91
92
expect ( headerCell . classList ) . toContain ( `cdk-column-${ component . columnsToRender [ index ] } ` ) ;
92
93
} ) ;
93
94
@@ -101,8 +102,9 @@ describe('CdkTable', () => {
101
102
it ( 'with the right accessibility roles' , ( ) => {
102
103
expect ( tableElement . getAttribute ( 'role' ) ) . toBe ( 'grid' ) ;
103
104
104
- expect ( getHeaderRow ( tableElement ) . getAttribute ( 'role' ) ) . toBe ( 'row' ) ;
105
- getHeaderCells ( tableElement ) . forEach ( cell => {
105
+ expect ( getHeaderRows ( tableElement ) [ 0 ] . getAttribute ( 'role' ) ) . toBe ( 'row' ) ;
106
+ const header = getHeaderRows ( tableElement ) [ 0 ] ;
107
+ getHeaderCells ( header ) . forEach ( cell => {
106
108
expect ( cell . getAttribute ( 'role' ) ) . toBe ( 'columnheader' ) ;
107
109
} ) ;
108
110
@@ -279,6 +281,40 @@ describe('CdkTable', () => {
279
281
expect ( getRows ( tableElement ) . length ) . toBe ( 0 ) ;
280
282
} ) ) ;
281
283
284
+ it ( 'should be able to render multiple header and footer rows' , ( ) => {
285
+ setupTableTestApp ( MultipleHeaderFooterRowsCdkTableApp ) ;
286
+ fixture . detectChanges ( ) ;
287
+
288
+ expectTableToMatchContent ( tableElement , [
289
+ [ 'first-header' ] ,
290
+ [ 'second-header' ] ,
291
+ [ 'first-footer' ] ,
292
+ [ 'second-footer' ] ,
293
+ ] ) ;
294
+ } ) ;
295
+
296
+ it ( 'should be able to render and change multiple header and footer rows' , ( ) => {
297
+ setupTableTestApp ( MultipleHeaderFooterRowsCdkTableApp ) ;
298
+ fixture . detectChanges ( ) ;
299
+
300
+ expectTableToMatchContent ( tableElement , [
301
+ [ 'first-header' ] ,
302
+ [ 'second-header' ] ,
303
+ [ 'first-footer' ] ,
304
+ [ 'second-footer' ] ,
305
+ ] ) ;
306
+
307
+ component . showAlternativeHeadersAndFooters = true ;
308
+ fixture . detectChanges ( ) ;
309
+
310
+ expectTableToMatchContent ( tableElement , [
311
+ [ 'first-header' ] ,
312
+ [ 'second-header' ] ,
313
+ [ 'first-footer' ] ,
314
+ [ 'second-footer' ] ,
315
+ ] ) ;
316
+ } ) ;
317
+
282
318
describe ( 'with different data inputs other than data source' , ( ) => {
283
319
let baseData : TestData [ ] = [
284
320
{ a : 'a_1' , b : 'b_1' , c : 'c_1' } ,
@@ -460,7 +496,8 @@ describe('CdkTable', () => {
460
496
it ( 'should be able to apply class-friendly css class names for the column cells' , ( ) => {
461
497
setupTableTestApp ( CrazyColumnNameCdkTableApp ) ;
462
498
// Column was named 'crazy-column-NAME-1!@#$%^-_&*()2'
463
- expect ( getHeaderCells ( tableElement ) [ 0 ] . classList )
499
+ const header = getHeaderRows ( tableElement ) [ 0 ] ;
500
+ expect ( getHeaderCells ( header ) [ 0 ] . classList )
464
501
. toContain ( 'cdk-column-crazy-column-NAME-1-------_----2' ) ;
465
502
} ) ;
466
503
@@ -488,7 +525,7 @@ describe('CdkTable', () => {
488
525
setupTableTestApp ( UndefinedColumnsCdkTableApp ) ;
489
526
490
527
// Header should be empty since there are no columns to display.
491
- const headerRow = getHeaderRow ( tableElement ) ;
528
+ const headerRow = getHeaderRows ( tableElement ) [ 0 ] ;
492
529
expect ( headerRow . textContent ) . toBe ( '' ) ;
493
530
494
531
// Rows should be empty since there are no columns to display.
@@ -657,6 +694,8 @@ describe('CdkTable', () => {
657
694
} ) ;
658
695
} ) ;
659
696
697
+
698
+
660
699
describe ( 'with trackBy' , ( ) => {
661
700
function createTestComponentWithTrackyByTable ( trackByStrategy ) {
662
701
fixture = createComponent ( TrackByCdkTableApp ) ;
@@ -1053,6 +1092,62 @@ class NullDataCdkTableApp {
1053
1092
dataSource = observableOf ( null ) ;
1054
1093
}
1055
1094
1095
+
1096
+ @Component ( {
1097
+ template : `
1098
+ <cdk-table [dataSource]="[]">
1099
+ <ng-container cdkColumnDef="first-header">
1100
+ <th cdk-header-cell *cdkHeaderCellDef> first-header </th>
1101
+ </ng-container>
1102
+
1103
+ <ng-container cdkColumnDef="second-header">
1104
+ <th cdk-header-cell *cdkHeaderCellDef> second-header </th>
1105
+ </ng-container>
1106
+
1107
+ <ng-container cdkColumnDef="first-footer">
1108
+ <td cdk-footer-cell *cdkFooterCellDef> first-footer </td>
1109
+ </ng-container>
1110
+
1111
+ <ng-container cdkColumnDef="second-footer">
1112
+ <td cdk-footer-cell *cdkFooterCellDef> second-footer </td>
1113
+ </ng-container>
1114
+
1115
+ <ng-container *ngIf="!showAlternativeHeadersAndFooters">
1116
+ <tr cdk-header-row *cdkHeaderRowDef="['first-header']"></tr>
1117
+ <tr cdk-header-row *cdkHeaderRowDef="['second-header']"></tr>
1118
+ <tr cdk-footer-row *cdkFooterRowDef="['first-footer']"></tr>
1119
+ <tr cdk-footer-row *cdkFooterRowDef="['second-footer']"></tr>
1120
+ </ng-container>
1121
+
1122
+ <ng-container cdkColumnDef="alt-first-header">
1123
+ <th cdk-header-cell *cdkHeaderCellDef> alt-first-header </th>
1124
+ </ng-container>
1125
+
1126
+ <ng-container cdkColumnDef="alt-second-header">
1127
+ <th cdk-header-cell *cdkHeaderCellDef> alt-second-header </th>
1128
+ </ng-container>
1129
+
1130
+ <ng-container cdkColumnDef="alt-first-footer">
1131
+ <td cdk-footer-cell *cdkFooterCellDef> alt-first-footer </td>
1132
+ </ng-container>
1133
+
1134
+ <ng-container cdkColumnDef="alt-second-footer">
1135
+ <td cdk-footer-cell *cdkFooterCellDef> alt-second-footer </td>
1136
+ </ng-container>
1137
+
1138
+ <ng-container *ngIf="showAlternativeHeadersAndFooters">
1139
+ <tr cdk-header-row *cdkHeaderRowDef="['alt-first-header']"></tr>
1140
+ <tr cdk-header-row *cdkHeaderRowDef="['alt-second-header']"></tr>
1141
+ <tr cdk-footer-row *cdkFooterRowDef="['alt-first-footer']"></tr>
1142
+ <tr cdk-footer-row *cdkFooterRowDef="['alt-second-footer']"></tr>
1143
+ </ng-container>
1144
+ </cdk-table>
1145
+ `
1146
+ } )
1147
+ class MultipleHeaderFooterRowsCdkTableApp {
1148
+ showAlternativeHeadersAndFooters = false ;
1149
+ }
1150
+
1056
1151
@Component ( {
1057
1152
template : `
1058
1153
<cdk-table [dataSource]="dataSource" [multiTemplateDataRows]="multiTemplateDataRows">
@@ -1586,42 +1681,62 @@ function getElements(element: Element, query: string): Element[] {
1586
1681
return [ ] . slice . call ( element . querySelectorAll ( query ) ) ;
1587
1682
}
1588
1683
1589
- function getHeaderRow ( tableElement : Element ) : Element {
1590
- return tableElement . querySelector ( '.cdk-header-row' ) ! ;
1684
+ function getHeaderRows ( tableElement : Element ) : Element [ ] {
1685
+ return [ ] . slice . call ( tableElement . querySelectorAll ( '.cdk-header-row' ) ) ! ;
1591
1686
}
1592
1687
1593
- function getFooterRow ( tableElement : Element ) : Element {
1594
- return tableElement . querySelector ( '.cdk-footer-row' ) ! ;
1688
+ function getFooterRows ( tableElement : Element ) : Element [ ] {
1689
+ return [ ] . slice . call ( tableElement . querySelectorAll ( '.cdk-footer-row' ) ) ! ;
1595
1690
}
1596
1691
1597
1692
function getRows ( tableElement : Element ) : Element [ ] {
1598
1693
return getElements ( tableElement , '.cdk-row' ) ;
1599
1694
}
1695
+
1600
1696
function getCells ( row : Element ) : Element [ ] {
1601
- return row ? getElements ( row , '.cdk-cell' ) : [ ] ;
1697
+ if ( ! row ) {
1698
+ return [ ] ;
1699
+ }
1700
+
1701
+ let cells = getElements ( row , 'cdk-cell' ) ;
1702
+ if ( ! cells . length ) {
1703
+ cells = getElements ( row , 'td' ) ;
1704
+ }
1705
+
1706
+ return cells ;
1602
1707
}
1603
1708
1604
- function getHeaderCells ( tableElement : Element ) : Element [ ] {
1605
- return getElements ( getHeaderRow ( tableElement ) , '.cdk-header-cell' ) ;
1709
+ function getHeaderCells ( headerRow : Element ) : Element [ ] {
1710
+ let cells = getElements ( headerRow , 'cdk-header-cell' ) ;
1711
+ if ( ! cells . length ) {
1712
+ cells = getElements ( headerRow , 'th' ) ;
1713
+ }
1714
+
1715
+ return cells ;
1606
1716
}
1607
1717
1608
- function getFooterCells ( tableElement : Element ) : Element [ ] {
1609
- return getElements ( getFooterRow ( tableElement ) , '.cdk-footer-cell' ) ;
1718
+ function getFooterCells ( footerRow : Element ) : Element [ ] {
1719
+ let cells = getElements ( footerRow , 'cdk-footer-cell' ) ;
1720
+ if ( ! cells . length ) {
1721
+ cells = getElements ( footerRow , 'td' ) ;
1722
+ }
1723
+
1724
+ return cells ;
1610
1725
}
1611
1726
1612
1727
function getActualTableContent ( tableElement : Element ) : string [ ] [ ] {
1613
1728
let actualTableContent : Element [ ] [ ] = [ ] ;
1614
- if ( getHeaderRow ( tableElement ) ) {
1615
- actualTableContent . push ( getHeaderCells ( tableElement ) ) ;
1616
- }
1729
+ getHeaderRows ( tableElement ) . forEach ( row => {
1730
+ actualTableContent . push ( getHeaderCells ( row ) ) ;
1731
+ } ) ;
1617
1732
1618
1733
// Check data row cells
1619
1734
const rows = getRows ( tableElement ) . map ( row => getCells ( row ) ) ;
1620
1735
actualTableContent = actualTableContent . concat ( rows ) ;
1621
1736
1622
- if ( getFooterRow ( tableElement ) ) {
1623
- actualTableContent . push ( getFooterCells ( tableElement ) ) ;
1624
- }
1737
+ getFooterRows ( tableElement ) . forEach ( row => {
1738
+ actualTableContent . push ( getFooterCells ( row ) ) ;
1739
+ } ) ;
1625
1740
1626
1741
// Convert the nodes into their text content;
1627
1742
return actualTableContent . map ( row => row . map ( cell => cell . textContent ! . trim ( ) ) ) ;
0 commit comments