Skip to content

Commit c0af9f7

Browse files
feat(cdk/table): add directive to enable recycle view repeater
1 parent 27e60e8 commit c0af9f7

File tree

16 files changed

+254
-12
lines changed

16 files changed

+254
-12
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,
@@ -80,6 +81,19 @@ import {
8081
} from './table-errors';
8182
import {CDK_TABLE} from './tokens';
8283

84+
85+
/**
86+
* Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with
87+
* tables that animate rows.
88+
*/
89+
@Directive({
90+
selector: 'cdk-table[cdkRecycleRows], table[cdk-table][cdkRecycleRows]',
91+
providers: [
92+
{provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy},
93+
],
94+
})
95+
export class CdkRecycleRows {}
96+
8397
/** Interface used to provide an outlet for rows to be inserted into. */
8498
export interface RowOutlet {
8599
viewContainer: ViewContainerRef;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
table {
2+
width: 100%;
3+
}
4+
5+
th {
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 cdk-table cdkRecycleRows [dataSource]="dataSource">
2+
<!-- Position Column -->
3+
<ng-container cdkColumnDef="position">
4+
<th 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 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 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 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+
table {
2+
width: 100%;
3+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<table mat-table matRecycleRows [dataSource]="dataSource" class="mat-elevation-z8">
2+
3+
<!--- Note that these columns can be defined in any order.
4+
The actual rendered columns are set as a property on the row definition" -->
5+
6+
<!-- Position Column -->
7+
<ng-container matColumnDef="position">
8+
<th mat-header-cell *matHeaderCellDef> No. </th>
9+
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
10+
</ng-container>
11+
12+
<!-- Name Column -->
13+
<ng-container matColumnDef="name">
14+
<th mat-header-cell *matHeaderCellDef> Name </th>
15+
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
16+
</ng-container>
17+
18+
<!-- Weight Column -->
19+
<ng-container matColumnDef="weight">
20+
<th mat-header-cell *matHeaderCellDef> Weight </th>
21+
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
22+
</ng-container>
23+
24+
<!-- Symbol Column -->
25+
<ng-container matColumnDef="symbol">
26+
<th mat-header-cell *matHeaderCellDef> Symbol </th>
27+
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
28+
</ng-container>
29+
30+
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
31+
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
32+
</table>
33+
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/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[cdkRecycleRows], table[mat-table][matRecycleRows]',
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 {MatTable, MatRecycleRows} 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[matRecycleRows], table[mat-table][matRecycleRows]',
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.

tools/public_api_guard/cdk/table.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ export declare class CdkNoDataRow {
173173
static ɵfac: i0.ɵɵFactoryDef<CdkNoDataRow, never>;
174174
}
175175

176+
export declare class CdkRecycleRows {
177+
static ɵdir: i0.ɵɵDirectiveDefWithMeta<CdkRecycleRows, "cdk-table[cdkRecycleRows], table[cdk-table][cdkRecycleRows]", never, {}, {}, never>;
178+
static ɵfac: i0.ɵɵFactoryDef<CdkRecycleRows, never>;
179+
}
180+
176181
export declare class CdkRow {
177182
static ɵcmp: i0.ɵɵComponentDefWithMeta<CdkRow, "cdk-row, tr[cdk-row]", never, {}, {}, never, never>;
178183
static ɵfac: i0.ɵɵFactoryDef<CdkRow, never>;
@@ -247,7 +252,7 @@ export declare class CdkTable<T> implements AfterContentChecked, CollectionViewe
247252

248253
export declare class CdkTableModule {
249254
static ɵinj: i0.ɵɵInjectorDef<CdkTableModule>;
250-
static ɵmod: i0.ɵɵNgModuleDefWithMeta<CdkTableModule, [typeof i1.CdkTable, typeof i2.CdkRowDef, typeof i3.CdkCellDef, typeof i2.CdkCellOutlet, typeof i3.CdkHeaderCellDef, typeof i3.CdkFooterCellDef, typeof i3.CdkColumnDef, typeof i3.CdkCell, typeof i2.CdkRow, typeof i3.CdkHeaderCell, typeof i3.CdkFooterCell, typeof i2.CdkHeaderRow, typeof i2.CdkHeaderRowDef, typeof i2.CdkFooterRow, typeof i2.CdkFooterRowDef, typeof i1.DataRowOutlet, typeof i1.HeaderRowOutlet, typeof i1.FooterRowOutlet, typeof i4.CdkTextColumn, typeof i2.CdkNoDataRow, typeof i1.NoDataRowOutlet], [typeof i5.ScrollingModule], [typeof i1.CdkTable, typeof i2.CdkRowDef, typeof i3.CdkCellDef, typeof i2.CdkCellOutlet, typeof i3.CdkHeaderCellDef, typeof i3.CdkFooterCellDef, typeof i3.CdkColumnDef, typeof i3.CdkCell, typeof i2.CdkRow, typeof i3.CdkHeaderCell, typeof i3.CdkFooterCell, typeof i2.CdkHeaderRow, typeof i2.CdkHeaderRowDef, typeof i2.CdkFooterRow, typeof i2.CdkFooterRowDef, typeof i1.DataRowOutlet, typeof i1.HeaderRowOutlet, typeof i1.FooterRowOutlet, typeof i4.CdkTextColumn, typeof i2.CdkNoDataRow, typeof i1.NoDataRowOutlet]>;
255+
static ɵmod: i0.ɵɵNgModuleDefWithMeta<CdkTableModule, [typeof i1.CdkTable, typeof i2.CdkRowDef, typeof i3.CdkCellDef, typeof i2.CdkCellOutlet, typeof i3.CdkHeaderCellDef, typeof i3.CdkFooterCellDef, typeof i3.CdkColumnDef, typeof i3.CdkCell, typeof i2.CdkRow, typeof i3.CdkHeaderCell, typeof i3.CdkFooterCell, typeof i2.CdkHeaderRow, typeof i2.CdkHeaderRowDef, typeof i2.CdkFooterRow, typeof i2.CdkFooterRowDef, typeof i1.DataRowOutlet, typeof i1.HeaderRowOutlet, typeof i1.FooterRowOutlet, typeof i4.CdkTextColumn, typeof i2.CdkNoDataRow, typeof i1.CdkRecycleRows, typeof i1.NoDataRowOutlet], [typeof i5.ScrollingModule], [typeof i1.CdkTable, typeof i2.CdkRowDef, typeof i3.CdkCellDef, typeof i2.CdkCellOutlet, typeof i3.CdkHeaderCellDef, typeof i3.CdkFooterCellDef, typeof i3.CdkColumnDef, typeof i3.CdkCell, typeof i2.CdkRow, typeof i3.CdkHeaderCell, typeof i3.CdkFooterCell, typeof i2.CdkHeaderRow, typeof i2.CdkHeaderRowDef, typeof i2.CdkFooterRow, typeof i2.CdkFooterRowDef, typeof i1.DataRowOutlet, typeof i1.HeaderRowOutlet, typeof i1.FooterRowOutlet, typeof i4.CdkTextColumn, typeof i2.CdkNoDataRow, typeof i1.CdkRecycleRows, typeof i1.NoDataRowOutlet]>;
251256
}
252257

253258
export declare class CdkTextColumn<T> implements OnDestroy, OnInit {

0 commit comments

Comments
 (0)