@@ -90,11 +90,14 @@ export class CdkTable<T> implements CollectionViewer {
90
90
private _renderChangeSubscription : Subscription | null ;
91
91
92
92
/** Map of all the user's defined columns (header and data cell template) identified by name. */
93
- private _columnDefinitionsByName = new Map < string , CdkColumnDef > ( ) ;
93
+ private _columnDefsByName = new Map < string , CdkColumnDef > ( ) ;
94
94
95
95
/** Differ used to find the changes in the data provided by the data source. */
96
96
private _dataDiffer : IterableDiffer < T > ;
97
97
98
+ /** Stores the row definition that does not have a when predicate. */
99
+ private _defaultRowDef : CdkRowDef < T > | null ;
100
+
98
101
/**
99
102
* Tracking function that will be used to check the differences in data changes. Used similarly
100
103
* to `ngFor` `trackBy` function. Optimize row operations by identifying a row based on its data
@@ -143,13 +146,13 @@ export class CdkTable<T> implements CollectionViewer {
143
146
* The column definitions provided by the user that contain what the header and cells should
144
147
* render for each column.
145
148
*/
146
- @ContentChildren ( CdkColumnDef ) _columnDefinitions : QueryList < CdkColumnDef > ;
149
+ @ContentChildren ( CdkColumnDef ) _columnDefs : QueryList < CdkColumnDef > ;
147
150
148
- /** Template used as the header container. */
149
- @ContentChild ( CdkHeaderRowDef ) _headerDefinition : CdkHeaderRowDef ;
151
+ /** Template definition used as the header container. */
152
+ @ContentChild ( CdkHeaderRowDef ) _headerDef : CdkHeaderRowDef ;
150
153
151
- /** Set of templates that used as the data row containers. */
152
- @ContentChildren ( CdkRowDef ) _rowDefinitions : QueryList < CdkRowDef > ;
154
+ /** Set of template definitions that used as the data row containers. */
155
+ @ContentChildren ( CdkRowDef ) _rowDefs : QueryList < CdkRowDef < T > > ;
153
156
154
157
constructor ( private readonly _differs : IterableDiffers ,
155
158
private readonly _changeDetectorRef : ChangeDetectorRef ,
@@ -167,13 +170,14 @@ export class CdkTable<T> implements CollectionViewer {
167
170
}
168
171
169
172
ngAfterContentInit ( ) {
170
- this . _cacheColumnDefinitionsByName ( ) ;
171
- this . _columnDefinitions . changes . subscribe ( ( ) => this . _cacheColumnDefinitionsByName ( ) ) ;
173
+ this . _cacheColumnDefsByName ( ) ;
174
+ this . _columnDefs . changes . subscribe ( ( ) => this . _cacheColumnDefsByName ( ) ) ;
172
175
this . _renderHeaderRow ( ) ;
173
176
}
174
177
175
178
ngAfterContentChecked ( ) {
176
179
this . _renderUpdatedColumns ( ) ;
180
+ this . _defaultRowDef = this . _rowDefs . find ( def => ! def . when ) || null ;
177
181
if ( this . dataSource && ! this . _renderChangeSubscription ) {
178
182
this . _observeRenderChanges ( ) ;
179
183
}
@@ -190,15 +194,14 @@ export class CdkTable<T> implements CollectionViewer {
190
194
}
191
195
}
192
196
193
-
194
197
/** Update the map containing the content's column definitions. */
195
- private _cacheColumnDefinitionsByName ( ) {
196
- this . _columnDefinitionsByName . clear ( ) ;
197
- this . _columnDefinitions . forEach ( columnDef => {
198
- if ( this . _columnDefinitionsByName . has ( columnDef . name ) ) {
198
+ private _cacheColumnDefsByName ( ) {
199
+ this . _columnDefsByName . clear ( ) ;
200
+ this . _columnDefs . forEach ( columnDef => {
201
+ if ( this . _columnDefsByName . has ( columnDef . name ) ) {
199
202
throw getTableDuplicateColumnNameError ( columnDef . name ) ;
200
203
}
201
- this . _columnDefinitionsByName . set ( columnDef . name , columnDef ) ;
204
+ this . _columnDefsByName . set ( columnDef . name , columnDef ) ;
202
205
} ) ;
203
206
}
204
207
@@ -208,8 +211,8 @@ export class CdkTable<T> implements CollectionViewer {
208
211
*/
209
212
private _renderUpdatedColumns ( ) {
210
213
// Re-render the rows when the row definition columns change.
211
- this . _rowDefinitions . forEach ( rowDefinition => {
212
- if ( ! ! rowDefinition . getColumnsDiff ( ) ) {
214
+ this . _rowDefs . forEach ( def => {
215
+ if ( ! ! def . getColumnsDiff ( ) ) {
213
216
// Reset the data to an empty array so that renderRowChanges will re-render all new rows.
214
217
this . _dataDiffer . diff ( [ ] ) ;
215
218
@@ -219,7 +222,7 @@ export class CdkTable<T> implements CollectionViewer {
219
222
} ) ;
220
223
221
224
// Re-render the header row if there is a difference in its columns.
222
- if ( this . _headerDefinition . getColumnsDiff ( ) ) {
225
+ if ( this . _headerDef . getColumnsDiff ( ) ) {
223
226
this . _headerRowPlaceholder . viewContainer . clear ( ) ;
224
227
this . _renderHeaderRow ( ) ;
225
228
}
@@ -264,14 +267,14 @@ export class CdkTable<T> implements CollectionViewer {
264
267
* Create the embedded view for the header template and place it in the header row view container.
265
268
*/
266
269
private _renderHeaderRow ( ) {
267
- const cells = this . _getHeaderCellTemplatesForRow ( this . _headerDefinition ) ;
270
+ const cells = this . _getHeaderCellTemplatesForRow ( this . _headerDef ) ;
268
271
if ( ! cells . length ) { return ; }
269
272
270
273
// TODO(andrewseguin): add some code to enforce that exactly
271
274
// one CdkCellOutlet was instantiated as a result
272
275
// of `createEmbeddedView`.
273
276
this . _headerRowPlaceholder . viewContainer
274
- . createEmbeddedView ( this . _headerDefinition . template , { cells} ) ;
277
+ . createEmbeddedView ( this . _headerDef . template , { cells} ) ;
275
278
276
279
cells . forEach ( cell => {
277
280
CdkCellOutlet . mostRecentCellOutlet . _viewContainer . createEmbeddedView ( cell . template , { } ) ;
@@ -301,15 +304,29 @@ export class CdkTable<T> implements CollectionViewer {
301
304
this . _updateRowContext ( ) ;
302
305
}
303
306
307
+ /**
308
+ * Finds the matching row definition that should be used for this row data. If there is only
309
+ * one row definition, it is returned. Otherwise, find the row definition that has a when
310
+ * predicate that returns true with the data. If none return true, return the default row
311
+ * definition.
312
+ */
313
+ _getRowDef ( data : T , i : number ) : CdkRowDef < T > {
314
+ if ( this . _rowDefs . length == 1 ) { return this . _rowDefs . first ; }
315
+
316
+ let rowDef = this . _rowDefs . find ( def => def . when && def . when ( data , i ) ) || this . _defaultRowDef ;
317
+ if ( ! rowDef ) {
318
+ throw Error ( 'Could not find a matching row definition for the provided row data' ) ;
319
+ }
320
+
321
+ return rowDef ;
322
+ }
323
+
304
324
/**
305
325
* Create the embedded view for the data row template and place it in the correct index location
306
326
* within the data row view container.
307
327
*/
308
328
private _insertRow ( rowData : T , index : number ) {
309
- // TODO(andrewseguin): Add when predicates to the row definitions
310
- // to find the right template to used based on
311
- // the data rather than choosing the first row definition.
312
- const row = this . _rowDefinitions . first ;
329
+ const row = this . _getRowDef ( rowData , index ) ;
313
330
314
331
// Row context that will be provided to both the created embedded row view and its cells.
315
332
const context : CdkCellOutletRowContext < T > = { $implicit : rowData } ;
@@ -353,7 +370,7 @@ export class CdkTable<T> implements CollectionViewer {
353
370
private _getHeaderCellTemplatesForRow ( headerDef : CdkHeaderRowDef ) : CdkHeaderCellDef [ ] {
354
371
if ( ! headerDef . columns ) { return [ ] ; }
355
372
return headerDef . columns . map ( columnId => {
356
- const column = this . _columnDefinitionsByName . get ( columnId ) ;
373
+ const column = this . _columnDefsByName . get ( columnId ) ;
357
374
358
375
if ( ! column ) {
359
376
throw getTableUnknownColumnError ( columnId ) ;
@@ -367,10 +384,10 @@ export class CdkTable<T> implements CollectionViewer {
367
384
* Returns the cell template definitions to insert in the provided row
368
385
* as defined by its list of columns to display.
369
386
*/
370
- private _getCellTemplatesForRow ( rowDef : CdkRowDef ) : CdkCellDef [ ] {
387
+ private _getCellTemplatesForRow ( rowDef : CdkRowDef < T > ) : CdkCellDef [ ] {
371
388
if ( ! rowDef . columns ) { return [ ] ; }
372
389
return rowDef . columns . map ( columnId => {
373
- const column = this . _columnDefinitionsByName . get ( columnId ) ;
390
+ const column = this . _columnDefsByName . get ( columnId ) ;
374
391
375
392
if ( ! column ) {
376
393
throw getTableUnknownColumnError ( columnId ) ;
0 commit comments