Skip to content

Commit f68662c

Browse files
feat(cdk/table): add directive to enable recycle view repeater (#21508)
1 parent 16f2a60 commit f68662c

File tree

17 files changed

+252
-13
lines changed

17 files changed

+252
-13
lines changed

src/cdk/table/table-module.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
*/
88

99
import {NgModule} from '@angular/core';
10-
import {HeaderRowOutlet, DataRowOutlet, CdkTable, FooterRowOutlet, NoDataRowOutlet} from './table';
10+
import {
11+
HeaderRowOutlet,
12+
DataRowOutlet,
13+
CdkTable,
14+
CdkRecycleRows,
15+
FooterRowOutlet,
16+
NoDataRowOutlet,
17+
} from './table';
1118
import {
1219
CdkCellOutlet, CdkFooterRow, CdkFooterRowDef, CdkHeaderRow, CdkHeaderRowDef, CdkRow,
1320
CdkRowDef,
@@ -41,6 +48,7 @@ const EXPORTED_DECLARATIONS = [
4148
FooterRowOutlet,
4249
CdkTextColumn,
4350
CdkNoDataRow,
51+
CdkRecycleRows,
4452
NoDataRowOutlet,
4553
];
4654

src/cdk/table/table.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
CollectionViewer,
1313
DataSource,
1414
_DisposeViewRepeaterStrategy,
15+
_RecycleViewRepeaterStrategy,
1516
isDataSource,
1617
_VIEW_REPEATER_STRATEGY,
1718
_ViewRepeater,
@@ -82,6 +83,19 @@ import {
8283
import {STICKY_POSITIONING_LISTENER, StickyPositioningListener} from './sticky-position-listener';
8384
import {CDK_TABLE} from './tokens';
8485

86+
87+
/**
88+
* Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with
89+
* tables that animate rows.
90+
*/
91+
@Directive({
92+
selector: 'cdk-table[recycleRows], table[cdk-table][recycleRows]',
93+
providers: [
94+
{provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy},
95+
],
96+
})
97+
export class CdkRecycleRows {}
98+
8599
/** Interface used to provide an outlet for rows to be inserted into. */
86100
export interface RowOutlet {
87101
viewContainer: ViewContainerRef;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.example-table {
2+
width: 100%;
3+
}
4+
5+
.example-row {
6+
text-align: left;
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<table class="example-table" cdk-table recycleRows [dataSource]="dataSource">
2+
<!-- Position Column -->
3+
<ng-container cdkColumnDef="position">
4+
<th class="example-row" cdk-header-cell *cdkHeaderCellDef> No. </th>
5+
<td cdk-cell *cdkCellDef="let element"> {{element.position}} </td>
6+
</ng-container>
7+
8+
<!-- Name Column -->
9+
<ng-container cdkColumnDef="name">
10+
<th class="example-row" cdk-header-cell *cdkHeaderCellDef> Name </th>
11+
<td cdk-cell *cdkCellDef="let element"> {{element.name}} </td>
12+
</ng-container>
13+
14+
<!-- Weight Column -->
15+
<ng-container cdkColumnDef="weight">
16+
<th class="example-row" cdk-header-cell *cdkHeaderCellDef> Weight </th>
17+
<td cdk-cell *cdkCellDef="let element"> {{element.weight}} </td>
18+
</ng-container>
19+
20+
<!-- Symbol Column -->
21+
<ng-container cdkColumnDef="symbol">
22+
<th class="example-row" cdk-header-cell *cdkHeaderCellDef> Symbol </th>
23+
<td cdk-cell *cdkCellDef="let element"> {{element.symbol}} </td>
24+
</ng-container>
25+
26+
<tr cdk-header-row *cdkHeaderRowDef="displayedColumns"></tr>
27+
<tr cdk-row *cdkRowDef="let row; columns: displayedColumns;"></tr>
28+
</table>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import {DataSource} from '@angular/cdk/collections';
2+
import {Component} from '@angular/core';
3+
import {BehaviorSubject, Observable} from 'rxjs';
4+
5+
export interface PeriodicElement {
6+
name: string;
7+
position: number;
8+
weight: number;
9+
symbol: string;
10+
}
11+
12+
const ELEMENT_DATA: PeriodicElement[] = [
13+
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
14+
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
15+
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
16+
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
17+
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
18+
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
19+
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
20+
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
21+
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
22+
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
23+
];
24+
25+
/**
26+
* @title Table that uses the recycle view repeater strategy.
27+
*/
28+
@Component({
29+
selector: 'cdk-table-recycle-rows-example',
30+
styleUrls: ['cdk-table-recycle-rows-example.css'],
31+
templateUrl: 'cdk-table-recycle-rows-example.html',
32+
})
33+
export class CdkTableRecycleRowsExample {
34+
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
35+
dataSource = new ExampleDataSource();
36+
}
37+
38+
/**
39+
* Data source to provide what data should be rendered in the table. Note that the data source
40+
* can retrieve its data in any way. In this case, the data source is provided a reference
41+
* to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
42+
* the underlying data. Instead, it only needs to take the data and send the table exactly what
43+
* should be rendered.
44+
*/
45+
export class ExampleDataSource extends DataSource<PeriodicElement> {
46+
/** Stream of data that is provided to the table. */
47+
data = new BehaviorSubject<PeriodicElement[]>(ELEMENT_DATA);
48+
49+
/** Connect function called by the table to retrieve one stream containing the data to render. */
50+
connect(): Observable<PeriodicElement[]> {
51+
return this.data;
52+
}
53+
54+
disconnect() {}
55+
}

src/components-examples/cdk/table/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@ import {CdkTableBasicExample} from './cdk-table-basic/cdk-table-basic-example';
55
import {
66
CdkTableFixedLayoutExample,
77
} from './cdk-table-fixed-layout/cdk-table-fixed-layout-example';
8-
8+
import {CdkTableRecycleRowsExample} from './cdk-table-recycle-rows/cdk-table-recycle-rows-example';
99
export {
1010
CdkTableBasicExample,
1111
CdkTableFlexBasicExample,
1212
CdkTableFixedLayoutExample,
13+
CdkTableRecycleRowsExample,
1314
};
1415

1516
const EXAMPLES = [
1617
CdkTableBasicExample,
1718
CdkTableFlexBasicExample,
1819
CdkTableFixedLayoutExample,
20+
CdkTableRecycleRowsExample,
1921
];
2022

2123
@NgModule({

src/components-examples/material/table/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
import {TableTextColumnExample} from './table-text-column/table-text-column-example';
4141
import {TableWrappedExample, WrapperTable} from './table-wrapped/table-wrapped-example';
4242
import {TableReorderableExample} from './table-reorderable/table-reorderable-example';
43+
import {TableRecycleRowsExample} from './table-recycle-rows/table-recycle-rows-example';
4344
import {TableHarnessExample} from './table-harness/table-harness-example';
4445

4546
export {
@@ -54,7 +55,8 @@ export {
5455
TableStickyFooterExample, TableStickyHeaderExample,
5556
TableTextColumnExample, TableTextColumnAdvancedExample,
5657
TableWrappedExample, WrapperTable,
57-
TableReorderableExample, TableHarnessExample,
58+
TableReorderableExample, TableRecycleRowsExample,
59+
TableHarnessExample,
5860
};
5961

6062
const EXAMPLES = [
@@ -69,7 +71,8 @@ const EXAMPLES = [
6971
TableStickyFooterExample, TableStickyHeaderExample,
7072
TableTextColumnExample, TableTextColumnAdvancedExample,
7173
TableWrappedExample, WrapperTable,
72-
TableReorderableExample, TableHarnessExample,
74+
TableReorderableExample, TableRecycleRowsExample,
75+
TableHarnessExample,
7376
];
7477

7578
@NgModule({
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.example-table {
2+
width: 100%;
3+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<table class="example-table mat-elevation-z8" mat-table recycleRows [dataSource]="dataSource">
2+
<!-- Position Column -->
3+
<ng-container matColumnDef="position">
4+
<th mat-header-cell *matHeaderCellDef> No. </th>
5+
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
6+
</ng-container>
7+
8+
<!-- Name Column -->
9+
<ng-container matColumnDef="name">
10+
<th mat-header-cell *matHeaderCellDef> Name </th>
11+
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
12+
</ng-container>
13+
14+
<!-- Weight Column -->
15+
<ng-container matColumnDef="weight">
16+
<th mat-header-cell *matHeaderCellDef> Weight </th>
17+
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
18+
</ng-container>
19+
20+
<!-- Symbol Column -->
21+
<ng-container matColumnDef="symbol">
22+
<th mat-header-cell *matHeaderCellDef> Symbol </th>
23+
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
24+
</ng-container>
25+
26+
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
27+
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
28+
</table>
29+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {Component} from '@angular/core';
2+
3+
export interface PeriodicElement {
4+
name: string;
5+
position: number;
6+
weight: number;
7+
symbol: string;
8+
}
9+
10+
const ELEMENT_DATA: PeriodicElement[] = [
11+
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
12+
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
13+
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
14+
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
15+
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
16+
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
17+
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
18+
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
19+
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
20+
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
21+
];
22+
23+
/**
24+
* @title Table that uses the recycle view repeater strategy.
25+
*/
26+
@Component({
27+
selector: 'table-recycle-rows-example',
28+
styleUrls: ['table-recycle-rows-example.css'],
29+
templateUrl: 'table-recycle-rows-example.html',
30+
})
31+
export class TableRecycleRowsExample {
32+
displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
33+
dataSource = ELEMENT_DATA;
34+
}

src/dev-app/table/table-demo.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<h3>Cdk table basic</h3>
22
<cdk-table-basic-example></cdk-table-basic-example>
33

4+
<h3>Cdk table with recycled rows</h3>
5+
<cdk-table-recycle-rows-example></cdk-table-recycle-rows-example>
6+
47
<h3>Cdk table basic with fixed column widths</h3>
58
<cdk-table-fixed-layout-example></cdk-table-fixed-layout-example>
69

@@ -10,6 +13,9 @@ <h3>Cdk table basic flex</h3>
1013
<h3>Table basic</h3>
1114
<table-basic-example></table-basic-example>
1215

16+
<h3>Table basic with recycled rows</h3>
17+
<table-recycle-rows-example></table-recycle-rows-example>
18+
1319
<h3>Table basic flex</h3>
1420
<table-flex-basic-example></table-flex-basic-example>
1521

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {NgModule} from '@angular/core';
1010
import {MatCommonModule} from '@angular/material-experimental/mdc-core';
11-
import {MatTable} from './table';
11+
import {MatRecycleRows, MatTable} from './table';
1212
import {CdkTableModule} from '@angular/cdk/table';
1313
import {
1414
MatCell,
@@ -33,6 +33,7 @@ import {MatTextColumn} from './text-column';
3333
const EXPORTED_DECLARATIONS = [
3434
// Table
3535
MatTable,
36+
MatRecycleRows,
3637

3738
// Template defs
3839
MatHeaderCellDef,

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

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,36 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation} from '@angular/core';
9+
import {
10+
ChangeDetectionStrategy,
11+
Component,
12+
Directive,
13+
OnInit,
14+
ViewEncapsulation
15+
} from '@angular/core';
1016
import {
1117
CDK_TABLE_TEMPLATE,
1218
CdkTable,
1319
_CoalescedStyleScheduler,
1420
_COALESCED_STYLE_SCHEDULER,
1521
} from '@angular/cdk/table';
16-
import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections';
22+
import {
23+
_DisposeViewRepeaterStrategy,
24+
_RecycleViewRepeaterStrategy,
25+
_VIEW_REPEATER_STRATEGY
26+
} from '@angular/cdk/collections';
27+
28+
/**
29+
* Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with
30+
* tables that animate rows.
31+
*/
32+
@Directive({
33+
selector: 'mat-table[recycleRows], table[mat-table][recycleRows]',
34+
providers: [
35+
{provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy},
36+
],
37+
})
38+
export class MatRecycleRows {}
1739

1840
@Component({
1941
selector: 'mat-table, table[mat-table]',

src/material/table/table-module.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import {NgModule} from '@angular/core';
10-
import {MatTable} from './table';
10+
import {MatRecycleRows, MatTable} from './table';
1111
import {CdkTableModule} from '@angular/cdk/table';
1212
import {
1313
MatCell,
@@ -16,7 +16,7 @@ import {
1616
MatFooterCell,
1717
MatFooterCellDef,
1818
MatHeaderCell,
19-
MatHeaderCellDef
19+
MatHeaderCellDef,
2020
} from './cell';
2121
import {
2222
MatFooterRow,
@@ -33,6 +33,7 @@ import {MatCommonModule} from '@angular/material/core';
3333
const EXPORTED_DECLARATIONS = [
3434
// Table
3535
MatTable,
36+
MatRecycleRows,
3637

3738
// Template defs
3839
MatHeaderCellDef,

src/material/table/table.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,24 @@ import {
1212
CDK_TABLE,
1313
_CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER
1414
} from '@angular/cdk/table';
15-
import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core';
16-
import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections';
15+
import {ChangeDetectionStrategy, Component, Directive, ViewEncapsulation} from '@angular/core';
16+
import {
17+
_DisposeViewRepeaterStrategy,
18+
_RecycleViewRepeaterStrategy,
19+
_VIEW_REPEATER_STRATEGY
20+
} from '@angular/cdk/collections';
21+
22+
/**
23+
* Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with
24+
* tables that animate rows.
25+
*/
26+
@Directive({
27+
selector: 'mat-table[recycleRows], table[mat-table][recycleRows]',
28+
providers: [
29+
{provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy},
30+
],
31+
})
32+
export class MatRecycleRows {}
1733

1834
/**
1935
* Wrapper for the CdkTable with Material design styles.

0 commit comments

Comments
 (0)