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 {