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