From 6fb5e690c45201459f44aa4bc759f814c56123d5 Mon Sep 17 00:00:00 2001 From: Michael-James <2666285+MichaelJamesParsons@users.noreply.github.com> Date: Fri, 5 Feb 2021 01:56:26 -0800 Subject: [PATCH] feat(cdk/table): add directive to enable recycle view repeater (#21508) --- src/cdk/table/table-module.ts | 10 +++- src/cdk/table/table.ts | 14 +++++ .../cdk-table-recycle-rows-example.css | 7 +++ .../cdk-table-recycle-rows-example.html | 28 ++++++++++ .../cdk-table-recycle-rows-example.ts | 55 +++++++++++++++++++ src/components-examples/cdk/table/index.ts | 4 +- .../material/table/index.ts | 7 ++- .../table-recycle-rows-example.css | 3 + .../table-recycle-rows-example.html | 29 ++++++++++ .../table-recycle-rows-example.ts | 34 ++++++++++++ src/dev-app/table/table-demo.html | 6 ++ src/material-experimental/mdc-table/module.ts | 3 +- src/material-experimental/mdc-table/table.ts | 26 ++++++++- src/material/table/table-module.ts | 5 +- src/material/table/table.ts | 20 ++++++- tools/public_api_guard/cdk/table.d.ts | 7 ++- tools/public_api_guard/material/table.d.ts | 7 ++- 17 files changed, 252 insertions(+), 13 deletions(-) create mode 100644 src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.css create mode 100644 src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.html create mode 100644 src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.ts create mode 100644 src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.css create mode 100644 src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.html create mode 100644 src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.ts diff --git a/src/cdk/table/table-module.ts b/src/cdk/table/table-module.ts index e4dcfdb1b019..32bb8cd7fcd3 100644 --- a/src/cdk/table/table-module.ts +++ b/src/cdk/table/table-module.ts @@ -7,7 +7,14 @@ */ import {NgModule} from '@angular/core'; -import {HeaderRowOutlet, DataRowOutlet, CdkTable, FooterRowOutlet, NoDataRowOutlet} from './table'; +import { + HeaderRowOutlet, + DataRowOutlet, + CdkTable, + CdkRecycleRows, + FooterRowOutlet, + NoDataRowOutlet, +} from './table'; import { CdkCellOutlet, CdkFooterRow, CdkFooterRowDef, CdkHeaderRow, CdkHeaderRowDef, CdkRow, CdkRowDef, @@ -41,6 +48,7 @@ const EXPORTED_DECLARATIONS = [ FooterRowOutlet, CdkTextColumn, CdkNoDataRow, + CdkRecycleRows, NoDataRowOutlet, ]; diff --git a/src/cdk/table/table.ts b/src/cdk/table/table.ts index 634bb190bd12..18ed91e4b024 100644 --- a/src/cdk/table/table.ts +++ b/src/cdk/table/table.ts @@ -12,6 +12,7 @@ import { CollectionViewer, DataSource, _DisposeViewRepeaterStrategy, + _RecycleViewRepeaterStrategy, isDataSource, _VIEW_REPEATER_STRATEGY, _ViewRepeater, @@ -82,6 +83,19 @@ import { import {STICKY_POSITIONING_LISTENER, StickyPositioningListener} from './sticky-position-listener'; import {CDK_TABLE} from './tokens'; + +/** + * Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with + * tables that animate rows. + */ +@Directive({ + selector: 'cdk-table[recycleRows], table[cdk-table][recycleRows]', + providers: [ + {provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy}, + ], +}) +export class CdkRecycleRows {} + /** Interface used to provide an outlet for rows to be inserted into. */ export interface RowOutlet { viewContainer: ViewContainerRef; diff --git a/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.css b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.css new file mode 100644 index 000000000000..3c247bd25f0f --- /dev/null +++ b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.css @@ -0,0 +1,7 @@ +.example-table { + width: 100%; +} + +.example-row { + text-align: left; +} diff --git a/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.html b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.html new file mode 100644 index 000000000000..866667d2b09e --- /dev/null +++ b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No. {{element.position}} Name {{element.name}} Weight {{element.weight}} Symbol {{element.symbol}}
diff --git a/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.ts b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.ts new file mode 100644 index 000000000000..ea1fcfe1093a --- /dev/null +++ b/src/components-examples/cdk/table/cdk-table-recycle-rows/cdk-table-recycle-rows-example.ts @@ -0,0 +1,55 @@ +import {DataSource} from '@angular/cdk/collections'; +import {Component} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +export interface PeriodicElement { + name: string; + position: number; + weight: number; + symbol: string; +} + +const ELEMENT_DATA: PeriodicElement[] = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, +]; + +/** + * @title Table that uses the recycle view repeater strategy. + */ +@Component({ + selector: 'cdk-table-recycle-rows-example', + styleUrls: ['cdk-table-recycle-rows-example.css'], + templateUrl: 'cdk-table-recycle-rows-example.html', +}) +export class CdkTableRecycleRowsExample { + displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; + dataSource = new ExampleDataSource(); +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + /** Stream of data that is provided to the table. */ + data = new BehaviorSubject(ELEMENT_DATA); + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + return this.data; + } + + disconnect() {} +} diff --git a/src/components-examples/cdk/table/index.ts b/src/components-examples/cdk/table/index.ts index 6944295d4ede..5e5a9c453bfc 100644 --- a/src/components-examples/cdk/table/index.ts +++ b/src/components-examples/cdk/table/index.ts @@ -5,17 +5,19 @@ import {CdkTableBasicExample} from './cdk-table-basic/cdk-table-basic-example'; import { CdkTableFixedLayoutExample, } from './cdk-table-fixed-layout/cdk-table-fixed-layout-example'; - +import {CdkTableRecycleRowsExample} from './cdk-table-recycle-rows/cdk-table-recycle-rows-example'; export { CdkTableBasicExample, CdkTableFlexBasicExample, CdkTableFixedLayoutExample, + CdkTableRecycleRowsExample, }; const EXAMPLES = [ CdkTableBasicExample, CdkTableFlexBasicExample, CdkTableFixedLayoutExample, + CdkTableRecycleRowsExample, ]; @NgModule({ diff --git a/src/components-examples/material/table/index.ts b/src/components-examples/material/table/index.ts index 398981163e7e..30509efb1800 100644 --- a/src/components-examples/material/table/index.ts +++ b/src/components-examples/material/table/index.ts @@ -40,6 +40,7 @@ import { import {TableTextColumnExample} from './table-text-column/table-text-column-example'; import {TableWrappedExample, WrapperTable} from './table-wrapped/table-wrapped-example'; import {TableReorderableExample} from './table-reorderable/table-reorderable-example'; +import {TableRecycleRowsExample} from './table-recycle-rows/table-recycle-rows-example'; import {TableHarnessExample} from './table-harness/table-harness-example'; export { @@ -54,7 +55,8 @@ export { TableStickyFooterExample, TableStickyHeaderExample, TableTextColumnExample, TableTextColumnAdvancedExample, TableWrappedExample, WrapperTable, - TableReorderableExample, TableHarnessExample, + TableReorderableExample, TableRecycleRowsExample, + TableHarnessExample, }; const EXAMPLES = [ @@ -69,7 +71,8 @@ const EXAMPLES = [ TableStickyFooterExample, TableStickyHeaderExample, TableTextColumnExample, TableTextColumnAdvancedExample, TableWrappedExample, WrapperTable, - TableReorderableExample, TableHarnessExample, + TableReorderableExample, TableRecycleRowsExample, + TableHarnessExample, ]; @NgModule({ diff --git a/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.css b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.css new file mode 100644 index 000000000000..cedd44731369 --- /dev/null +++ b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.css @@ -0,0 +1,3 @@ +.example-table { + width: 100%; +} diff --git a/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.html b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.html new file mode 100644 index 000000000000..d35381653f3a --- /dev/null +++ b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.html @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No. {{element.position}} Name {{element.name}} Weight {{element.weight}} Symbol {{element.symbol}}
+ diff --git a/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.ts b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.ts new file mode 100644 index 000000000000..924df7aec559 --- /dev/null +++ b/src/components-examples/material/table/table-recycle-rows/table-recycle-rows-example.ts @@ -0,0 +1,34 @@ +import {Component} from '@angular/core'; + +export interface PeriodicElement { + name: string; + position: number; + weight: number; + symbol: string; +} + +const ELEMENT_DATA: PeriodicElement[] = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, +]; + +/** + * @title Table that uses the recycle view repeater strategy. + */ +@Component({ + selector: 'table-recycle-rows-example', + styleUrls: ['table-recycle-rows-example.css'], + templateUrl: 'table-recycle-rows-example.html', +}) +export class TableRecycleRowsExample { + displayedColumns: string[] = ['position', 'name', 'weight', 'symbol']; + dataSource = ELEMENT_DATA; +} diff --git a/src/dev-app/table/table-demo.html b/src/dev-app/table/table-demo.html index c4c07b9e4783..4b85241a1952 100644 --- a/src/dev-app/table/table-demo.html +++ b/src/dev-app/table/table-demo.html @@ -1,6 +1,9 @@

Cdk table basic

+

Cdk table with recycled rows

+ +

Cdk table basic with fixed column widths

@@ -10,6 +13,9 @@

Cdk table basic flex

Table basic

+

Table basic with recycled rows

+ +

Table basic flex

diff --git a/src/material-experimental/mdc-table/module.ts b/src/material-experimental/mdc-table/module.ts index 1522deb687be..6245dfe3e8d7 100644 --- a/src/material-experimental/mdc-table/module.ts +++ b/src/material-experimental/mdc-table/module.ts @@ -8,7 +8,7 @@ import {NgModule} from '@angular/core'; import {MatCommonModule} from '@angular/material-experimental/mdc-core'; -import {MatTable} from './table'; +import {MatRecycleRows, MatTable} from './table'; import {CdkTableModule} from '@angular/cdk/table'; import { MatCell, @@ -33,6 +33,7 @@ import {MatTextColumn} from './text-column'; const EXPORTED_DECLARATIONS = [ // Table MatTable, + MatRecycleRows, // Template defs MatHeaderCellDef, diff --git a/src/material-experimental/mdc-table/table.ts b/src/material-experimental/mdc-table/table.ts index cda399570668..5797ffe6226f 100644 --- a/src/material-experimental/mdc-table/table.ts +++ b/src/material-experimental/mdc-table/table.ts @@ -6,14 +6,36 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation} from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + Directive, + OnInit, + ViewEncapsulation +} from '@angular/core'; import { CDK_TABLE_TEMPLATE, CdkTable, _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER, } from '@angular/cdk/table'; -import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections'; +import { + _DisposeViewRepeaterStrategy, + _RecycleViewRepeaterStrategy, + _VIEW_REPEATER_STRATEGY +} from '@angular/cdk/collections'; + +/** + * Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with + * tables that animate rows. + */ +@Directive({ + selector: 'mat-table[recycleRows], table[mat-table][recycleRows]', + providers: [ + {provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy}, + ], +}) +export class MatRecycleRows {} @Component({ selector: 'mat-table, table[mat-table]', diff --git a/src/material/table/table-module.ts b/src/material/table/table-module.ts index 372bff81f11c..85ae6e67130e 100644 --- a/src/material/table/table-module.ts +++ b/src/material/table/table-module.ts @@ -7,7 +7,7 @@ */ import {NgModule} from '@angular/core'; -import {MatTable} from './table'; +import {MatRecycleRows, MatTable} from './table'; import {CdkTableModule} from '@angular/cdk/table'; import { MatCell, @@ -16,7 +16,7 @@ import { MatFooterCell, MatFooterCellDef, MatHeaderCell, - MatHeaderCellDef + MatHeaderCellDef, } from './cell'; import { MatFooterRow, @@ -33,6 +33,7 @@ import {MatCommonModule} from '@angular/material/core'; const EXPORTED_DECLARATIONS = [ // Table MatTable, + MatRecycleRows, // Template defs MatHeaderCellDef, diff --git a/src/material/table/table.ts b/src/material/table/table.ts index 0f3aa1a0574f..efaff39969c0 100644 --- a/src/material/table/table.ts +++ b/src/material/table/table.ts @@ -12,8 +12,24 @@ import { CDK_TABLE, _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER } from '@angular/cdk/table'; -import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core'; -import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections'; +import {ChangeDetectionStrategy, Component, Directive, ViewEncapsulation} from '@angular/core'; +import { + _DisposeViewRepeaterStrategy, + _RecycleViewRepeaterStrategy, + _VIEW_REPEATER_STRATEGY +} from '@angular/cdk/collections'; + +/** + * Enables the recycle view repeater strategy, which reduces rendering latency. Not compatible with + * tables that animate rows. + */ +@Directive({ + selector: 'mat-table[recycleRows], table[mat-table][recycleRows]', + providers: [ + {provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy}, + ], +}) +export class MatRecycleRows {} /** * Wrapper for the CdkTable with Material design styles. diff --git a/tools/public_api_guard/cdk/table.d.ts b/tools/public_api_guard/cdk/table.d.ts index 5982cbaf7e74..c722d4e36ea9 100644 --- a/tools/public_api_guard/cdk/table.d.ts +++ b/tools/public_api_guard/cdk/table.d.ts @@ -173,6 +173,11 @@ export declare class CdkNoDataRow { static ɵfac: i0.ɵɵFactoryDef; } +export declare class CdkRecycleRows { + static ɵdir: i0.ɵɵDirectiveDefWithMeta; + static ɵfac: i0.ɵɵFactoryDef; +} + export declare class CdkRow { static ɵcmp: i0.ɵɵComponentDefWithMeta; static ɵfac: i0.ɵɵFactoryDef; @@ -248,7 +253,7 @@ export declare class CdkTable implements AfterContentChecked, CollectionViewe export declare class CdkTableModule { static ɵinj: i0.ɵɵInjectorDef; - static ɵmod: i0.ɵɵNgModuleDefWithMeta; + static ɵmod: i0.ɵɵNgModuleDefWithMeta; } export declare class CdkTextColumn implements OnDestroy, OnInit { diff --git a/tools/public_api_guard/material/table.d.ts b/tools/public_api_guard/material/table.d.ts index 6af3bc69ba87..07b48a258742 100644 --- a/tools/public_api_guard/material/table.d.ts +++ b/tools/public_api_guard/material/table.d.ts @@ -88,6 +88,11 @@ export declare class MatNoDataRow extends CdkNoDataRow { static ɵfac: i0.ɵɵFactoryDef; } +export declare class MatRecycleRows { + static ɵdir: i0.ɵɵDirectiveDefWithMeta; + static ɵfac: i0.ɵɵFactoryDef; +} + export declare class MatRow extends CdkRow { static ɵcmp: i0.ɵɵComponentDefWithMeta; static ɵfac: i0.ɵɵFactoryDef; @@ -110,7 +115,7 @@ export declare class MatTableDataSource extends _MatTableDataSource; - static ɵmod: i0.ɵɵNgModuleDefWithMeta; + static ɵmod: i0.ɵɵNgModuleDefWithMeta; } export declare class MatTextColumn extends CdkTextColumn {