diff --git a/src/cdk-experimental/column-resize/resize-strategy.ts b/src/cdk-experimental/column-resize/resize-strategy.ts index 905c78ffb535..799ee1cb1f57 100644 --- a/src/cdk-experimental/column-resize/resize-strategy.ts +++ b/src/cdk-experimental/column-resize/resize-strategy.ts @@ -9,7 +9,7 @@ import {Inject, Injectable, OnDestroy, Provider} from '@angular/core'; import {DOCUMENT} from '@angular/common'; import {coerceCssPixelValue} from '@angular/cdk/coercion'; -import {CdkTable, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import {CdkTable, _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER} from '@angular/cdk/table'; import {ColumnResize} from './column-resize'; @@ -76,7 +76,8 @@ export abstract class ResizeStrategy { export class TableLayoutFixedResizeStrategy extends ResizeStrategy { constructor( protected readonly columnResize: ColumnResize, - protected readonly styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly styleScheduler: _CoalescedStyleScheduler, protected readonly table: CdkTable) { super(); } @@ -131,7 +132,8 @@ export class CdkFlexTableResizeStrategy extends ResizeStrategy implements OnDest constructor( protected readonly columnResize: ColumnResize, - protected readonly styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly styleScheduler: _CoalescedStyleScheduler, protected readonly table: CdkTable, @Inject(DOCUMENT) document: any) { super(); diff --git a/src/cdk/table/coalesced-style-scheduler.ts b/src/cdk/table/coalesced-style-scheduler.ts index d19517a59e81..3fdd0512e6ca 100644 --- a/src/cdk/table/coalesced-style-scheduler.ts +++ b/src/cdk/table/coalesced-style-scheduler.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {Injectable, NgZone, OnDestroy} from '@angular/core'; +import {Injectable, NgZone, OnDestroy, InjectionToken} from '@angular/core'; import {from, Subject} from 'rxjs'; import {take, takeUntil} from 'rxjs/operators'; @@ -18,6 +18,10 @@ export class _Schedule { endTasks: (() => unknown)[] = []; } +/** Injection token used to provide a coalesced style scheduler. */ +export const _COALESCED_STYLE_SCHEDULER = + new InjectionToken<_CoalescedStyleScheduler>('_COALESCED_STYLE_SCHEDULER'); + /** * Allows grouping up CSSDom mutations after the current execution context. * This can significantly improve performance when separate consecutive functions are diff --git a/src/cdk/table/sticky-styler.ts b/src/cdk/table/sticky-styler.ts index cdde20a97834..cb19195463c3 100644 --- a/src/cdk/table/sticky-styler.ts +++ b/src/cdk/table/sticky-styler.ts @@ -44,7 +44,11 @@ export class StickyStyler { constructor(private _isNativeHtmlTable: boolean, private _stickCellCss: string, public direction: Direction, - private _coalescedStyleScheduler: _CoalescedStyleScheduler, + /** + * @deprecated `_coalescedStyleScheduler` parameter to become required. + * @breaking-change 11.0.0 + */ + private _coalescedStyleScheduler?: _CoalescedStyleScheduler, private _isBrowser = true, private readonly _needsPositionStickyOnElement = true) { } @@ -70,7 +74,7 @@ export class StickyStyler { } // Coalesce with sticky row/column updates (and potentially other changes like column resize). - this._coalescedStyleScheduler.schedule(() => { + this._scheduleStyleChanges(() => { for (const element of elementsToClear) { this._removeStickyStyle(element, stickyDirections); } @@ -104,7 +108,7 @@ export class StickyStyler { const endPositions = this._getStickyEndColumnPositions(cellWidths, stickyEndStates); // Coalesce with sticky row updates (and potentially other changes like column resize). - this._coalescedStyleScheduler.schedule(() => { + this._scheduleStyleChanges(() => { const isRtl = this.direction === 'rtl'; const start = isRtl ? 'right' : 'left'; const end = isRtl ? 'left' : 'right'; @@ -168,7 +172,7 @@ export class StickyStyler { // Coalesce with other sticky row updates (top/bottom), sticky columns updates // (and potentially other changes like column resize). - this._coalescedStyleScheduler.schedule(() => { + this._scheduleStyleChanges(() => { for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) { if (!states[rowIndex]) { continue; @@ -196,7 +200,7 @@ export class StickyStyler { const tfoot = tableElement.querySelector('tfoot')!; // Coalesce with other sticky updates (and potentially other changes like column resize). - this._coalescedStyleScheduler.schedule(() => { + this._scheduleStyleChanges(() => { if (stickyStates.some(state => !state)) { this._removeStickyStyle(tfoot, ['bottom']); } else { @@ -333,4 +337,17 @@ export class StickyStyler { return positions; } + + /** + * Schedules styles to be applied when the style scheduler deems appropriate. + * @breaking-change 11.0.0 This method can be removed in favor of calling + * `CoalescedStyleScheduler.schedule` directly once the scheduler is a required parameter. + */ + private _scheduleStyleChanges(changes: () => void) { + if (this._coalescedStyleScheduler) { + this._coalescedStyleScheduler.schedule(changes); + } else { + changes(); + } + } } diff --git a/src/cdk/table/table.ts b/src/cdk/table/table.ts index c6c8495f88bf..fc1d8fee083a 100644 --- a/src/cdk/table/table.ts +++ b/src/cdk/table/table.ts @@ -58,7 +58,7 @@ import { } from 'rxjs'; import {takeUntil} from 'rxjs/operators'; import {CdkColumnDef} from './cell'; -import {_CoalescedStyleScheduler} from './coalesced-style-scheduler'; +import {_CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER} from './coalesced-style-scheduler'; import { BaseRowDef, CdkCellOutlet, @@ -202,7 +202,7 @@ export interface RenderRow { providers: [ {provide: CDK_TABLE, useExisting: CdkTable}, {provide: _VIEW_REPEATER_STRATEGY, useClass: _DisposeViewRepeaterStrategy}, - _CoalescedStyleScheduler, + {provide: _COALESCED_STYLE_SCHEDULER, useClass: _CoalescedStyleScheduler}, ] }) export class CdkTable implements AfterContentChecked, CollectionViewer, OnDestroy, OnInit { @@ -476,18 +476,23 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes constructor( protected readonly _differs: IterableDiffers, protected readonly _changeDetectorRef: ChangeDetectorRef, - protected readonly _coalescedStyleScheduler: _CoalescedStyleScheduler, protected readonly _elementRef: ElementRef, @Attribute('role') role: string, @Optional() protected readonly _dir: Directionality, @Inject(DOCUMENT) _document: any, private _platform: Platform, - // Optional for backwards compatibility, but a view repeater strategy will always - // be provided. + + /** + * @deprecated `_coalescedStyleScheduler`, `_viewRepeater` and `_viewportRuler` + * parameters to become required. + * @breaking-change 11.0.0 + */ @Optional() @Inject(_VIEW_REPEATER_STRATEGY) - protected readonly _viewRepeater: _ViewRepeater, RowContext>, + protected readonly _viewRepeater?: _ViewRepeater, RowContext>, + @Optional() @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly _coalescedStyleScheduler?: _CoalescedStyleScheduler, // Optional for backwards compatibility. The viewport ruler is provided in root. Therefore, // this property will never be null. // tslint:disable-next-line: lightweight-tokens - @Optional() private readonly _viewportRuler: ViewportRuler) { + @Optional() private readonly _viewportRuler?: ViewportRuler) { if (!role) { this._elementRef.nativeElement.setAttribute('role', 'grid'); } @@ -512,9 +517,12 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes // Table cell dimensions may change after resizing the window. Signal the sticky styler to // refresh its cache of cell widths the next time sticky styles are updated. - this._viewportRuler.change().pipe(takeUntil(this._onDestroy)).subscribe(() => { - this._forceRecalculateCellWidths = true; - }); + // @breaking-change 11.0.0 Remove null check for _viewportRuler once it's a required parameter. + if (this._viewportRuler) { + this._viewportRuler.change().pipe(takeUntil(this._onDestroy)).subscribe(() => { + this._forceRecalculateCellWidths = true; + }); + } } ngAfterContentChecked() { @@ -594,11 +602,14 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes return; } const viewContainer = this._rowOutlet.viewContainer; - this._viewRepeater.applyChanges( + + // @breaking-change 11.0.0 Remove null check for `_viewRepeater` + // once it's a required parameter in the constructor. + this._viewRepeater?.applyChanges( changes, viewContainer, (record: IterableChangeRecord>, - adjustedPreviousIndex: number|null, + _adjustedPreviousIndex: number|null, currentIndex: number|null) => this._getEmbeddedViewArgs(record.item, currentIndex!), (record) => record.item.data, (change: _ViewRepeaterItemChange, RowContext>) => { diff --git a/src/material-experimental/column-resize/overlay-handle.ts b/src/material-experimental/column-resize/overlay-handle.ts index 6c106148751d..47b0fbb17785 100644 --- a/src/material-experimental/column-resize/overlay-handle.ts +++ b/src/material-experimental/column-resize/overlay-handle.ts @@ -15,7 +15,11 @@ import { ViewEncapsulation, } from '@angular/core'; import {DOCUMENT} from '@angular/common'; -import {CdkColumnDef, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import { + CdkColumnDef, + _CoalescedStyleScheduler, + _COALESCED_STYLE_SCHEDULER, +} from '@angular/cdk/table'; import {Directionality} from '@angular/cdk/bidi'; import { ColumnResize, @@ -49,7 +53,8 @@ export class MatColumnResizeOverlayHandle extends ResizeOverlayHandle { protected readonly ngZone: NgZone, protected readonly resizeNotifier: ColumnResizeNotifierSource, protected readonly resizeRef: ResizeRef, - protected readonly styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly styleScheduler: _CoalescedStyleScheduler, @Inject(DOCUMENT) document: any) { super(); this.document = document; diff --git a/src/material-experimental/column-resize/resizable-directives/default-enabled-resizable.ts b/src/material-experimental/column-resize/resizable-directives/default-enabled-resizable.ts index 57d0d329ad70..58152822fc8d 100644 --- a/src/material-experimental/column-resize/resizable-directives/default-enabled-resizable.ts +++ b/src/material-experimental/column-resize/resizable-directives/default-enabled-resizable.ts @@ -18,7 +18,11 @@ import { import {DOCUMENT} from '@angular/common'; import {Directionality} from '@angular/cdk/bidi'; import {Overlay} from '@angular/cdk/overlay'; -import {CdkColumnDef, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import { + CdkColumnDef, + _CoalescedStyleScheduler, + _COALESCED_STYLE_SCHEDULER, +} from '@angular/cdk/table'; import { ColumnResize, ColumnResizeNotifierSource, @@ -52,7 +56,8 @@ export class MatDefaultResizable extends AbstractMatResizable { protected readonly overlay: Overlay, protected readonly resizeNotifier: ColumnResizeNotifierSource, protected readonly resizeStrategy: ResizeStrategy, - protected readonly styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly styleScheduler: _CoalescedStyleScheduler, protected readonly viewContainerRef: ViewContainerRef, protected readonly changeDetectorRef: ChangeDetectorRef) { super(); diff --git a/src/material-experimental/column-resize/resizable-directives/resizable.ts b/src/material-experimental/column-resize/resizable-directives/resizable.ts index e23343b69694..230d1891fc0d 100644 --- a/src/material-experimental/column-resize/resizable-directives/resizable.ts +++ b/src/material-experimental/column-resize/resizable-directives/resizable.ts @@ -18,7 +18,11 @@ import { import {DOCUMENT} from '@angular/common'; import {Directionality} from '@angular/cdk/bidi'; import {Overlay} from '@angular/cdk/overlay'; -import {CdkColumnDef, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import { + CdkColumnDef, + _CoalescedStyleScheduler, + _COALESCED_STYLE_SCHEDULER, +} from '@angular/cdk/table'; import { ColumnResize, ColumnResizeNotifierSource, @@ -51,7 +55,8 @@ export class MatResizable extends AbstractMatResizable { protected readonly overlay: Overlay, protected readonly resizeNotifier: ColumnResizeNotifierSource, protected readonly resizeStrategy: ResizeStrategy, - protected readonly styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) + protected readonly styleScheduler: _CoalescedStyleScheduler, protected readonly viewContainerRef: ViewContainerRef, protected readonly changeDetectorRef: ChangeDetectorRef) { super(); diff --git a/src/material-experimental/column-resize/resize-strategy.ts b/src/material-experimental/column-resize/resize-strategy.ts index df5b7c370dbd..750489f8ba92 100644 --- a/src/material-experimental/column-resize/resize-strategy.ts +++ b/src/material-experimental/column-resize/resize-strategy.ts @@ -8,7 +8,7 @@ import {Inject, Injectable, Provider} from '@angular/core'; import {DOCUMENT} from '@angular/common'; -import {CdkTable, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import {CdkTable, _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER} from '@angular/cdk/table'; import { ColumnResize, @@ -26,7 +26,7 @@ export {TABLE_LAYOUT_FIXED_RESIZE_STRATEGY_PROVIDER}; export class MatFlexTableResizeStrategy extends CdkFlexTableResizeStrategy { constructor( columnResize: ColumnResize, - styleScheduler: _CoalescedStyleScheduler, + @Inject(_COALESCED_STYLE_SCHEDULER) styleScheduler: _CoalescedStyleScheduler, table: CdkTable, @Inject(DOCUMENT) document: any) { super(columnResize, styleScheduler, table, document); diff --git a/src/material-experimental/mdc-table/table.ts b/src/material-experimental/mdc-table/table.ts index c77bde17a0ba..4bb0c8546110 100644 --- a/src/material-experimental/mdc-table/table.ts +++ b/src/material-experimental/mdc-table/table.ts @@ -7,7 +7,12 @@ */ import {ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation} from '@angular/core'; -import {CDK_TABLE_TEMPLATE, CdkTable, _CoalescedStyleScheduler} from '@angular/cdk/table'; +import { + CDK_TABLE_TEMPLATE, + CdkTable, + _CoalescedStyleScheduler, + _COALESCED_STYLE_SCHEDULER, +} from '@angular/cdk/table'; import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections'; @Component({ @@ -21,7 +26,7 @@ import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cd }, providers: [ {provide: CdkTable, useExisting: MatTable}, - _CoalescedStyleScheduler, + {provide: _COALESCED_STYLE_SCHEDULER, useClass: _CoalescedStyleScheduler}, // TODO(michaeljamesparsons) Abstract the view repeater strategy to a directive API so this code // is only included in the build if used. {provide: _VIEW_REPEATER_STRATEGY, useClass: _DisposeViewRepeaterStrategy}, diff --git a/src/material/table/table.ts b/src/material/table/table.ts index 468dfc2a69fc..0f3aa1a0574f 100644 --- a/src/material/table/table.ts +++ b/src/material/table/table.ts @@ -10,7 +10,7 @@ import { CDK_TABLE_TEMPLATE, CdkTable, CDK_TABLE, - _CoalescedStyleScheduler + _CoalescedStyleScheduler, _COALESCED_STYLE_SCHEDULER } from '@angular/cdk/table'; import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core'; import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cdk/collections'; @@ -33,7 +33,7 @@ import {_DisposeViewRepeaterStrategy, _VIEW_REPEATER_STRATEGY} from '@angular/cd {provide: _VIEW_REPEATER_STRATEGY, useClass: _DisposeViewRepeaterStrategy}, {provide: CdkTable, useExisting: MatTable}, {provide: CDK_TABLE, useExisting: MatTable}, - _CoalescedStyleScheduler, + {provide: _COALESCED_STYLE_SCHEDULER, useClass: _CoalescedStyleScheduler}, ], encapsulation: ViewEncapsulation.None, // See note on CdkTable for explanation on why this uses the default change detection strategy. diff --git a/tools/public_api_guard/cdk/table.d.ts b/tools/public_api_guard/cdk/table.d.ts index d4f4ae23f8d2..8325ea4e5683 100644 --- a/tools/public_api_guard/cdk/table.d.ts +++ b/tools/public_api_guard/cdk/table.d.ts @@ -1,3 +1,5 @@ +export declare const _COALESCED_STYLE_SCHEDULER: InjectionToken<_CoalescedStyleScheduler>; + export declare class _CoalescedStyleScheduler implements OnDestroy { constructor(_ngZone: NgZone); ngOnDestroy(): void; @@ -186,7 +188,7 @@ export declare class CdkRowDef extends BaseRowDef { export declare class CdkTable implements AfterContentChecked, CollectionViewer, OnDestroy, OnInit { protected readonly _changeDetectorRef: ChangeDetectorRef; - protected readonly _coalescedStyleScheduler: _CoalescedStyleScheduler; + protected readonly _coalescedStyleScheduler?: _CoalescedStyleScheduler | undefined; _contentColumnDefs: QueryList; _contentFooterRowDefs: QueryList; _contentHeaderRowDefs: QueryList; @@ -201,7 +203,7 @@ export declare class CdkTable implements AfterContentChecked, CollectionViewe _noDataRow: CdkNoDataRow; _noDataRowOutlet: NoDataRowOutlet; _rowOutlet: DataRowOutlet; - protected readonly _viewRepeater: _ViewRepeater, RowContext>; + protected readonly _viewRepeater?: _ViewRepeater, RowContext> | undefined; get dataSource(): CdkTableDataSourceInput; set dataSource(dataSource: CdkTableDataSourceInput); get fixedLayout(): boolean; @@ -216,7 +218,8 @@ export declare class CdkTable implements AfterContentChecked, CollectionViewe start: number; end: number; }>; - constructor(_differs: IterableDiffers, _changeDetectorRef: ChangeDetectorRef, _coalescedStyleScheduler: _CoalescedStyleScheduler, _elementRef: ElementRef, role: string, _dir: Directionality, _document: any, _platform: Platform, _viewRepeater: _ViewRepeater, RowContext>, _viewportRuler: ViewportRuler); + constructor(_differs: IterableDiffers, _changeDetectorRef: ChangeDetectorRef, _elementRef: ElementRef, role: string, _dir: Directionality, _document: any, _platform: Platform, + _viewRepeater?: _ViewRepeater, RowContext> | undefined, _coalescedStyleScheduler?: _CoalescedStyleScheduler | undefined, _viewportRuler?: ViewportRuler | undefined); _getRenderedRows(rowOutlet: RowOutlet): HTMLElement[]; _getRowDefs(data: T, dataIndex: number): CdkRowDef[]; addColumnDef(columnDef: CdkColumnDef): void; @@ -237,7 +240,7 @@ export declare class CdkTable implements AfterContentChecked, CollectionViewe static ngAcceptInputType_fixedLayout: BooleanInput; static ngAcceptInputType_multiTemplateDataRows: BooleanInput; static ɵcmp: i0.ɵɵComponentDefWithMeta, "cdk-table, table[cdk-table]", ["cdkTable"], { "trackBy": "trackBy"; "dataSource": "dataSource"; "multiTemplateDataRows": "multiTemplateDataRows"; "fixedLayout": "fixedLayout"; }, {}, ["_noDataRow", "_contentColumnDefs", "_contentRowDefs", "_contentHeaderRowDefs", "_contentFooterRowDefs"], ["caption", "colgroup, col"]>; - static ɵfac: i0.ɵɵFactoryDef, [null, null, null, null, { attribute: "role"; }, { optional: true; }, null, null, { optional: true; }, { optional: true; }]>; + static ɵfac: i0.ɵɵFactoryDef, [null, null, null, { attribute: "role"; }, { optional: true; }, null, null, { optional: true; }, { optional: true; }, { optional: true; }]>; } export declare class CdkTableModule { @@ -322,7 +325,8 @@ export declare type StickyDirection = 'top' | 'bottom' | 'left' | 'right'; export declare class StickyStyler { direction: Direction; - constructor(_isNativeHtmlTable: boolean, _stickCellCss: string, direction: Direction, _coalescedStyleScheduler: _CoalescedStyleScheduler, _isBrowser?: boolean, _needsPositionStickyOnElement?: boolean); + constructor(_isNativeHtmlTable: boolean, _stickCellCss: string, direction: Direction, + _coalescedStyleScheduler?: _CoalescedStyleScheduler | undefined, _isBrowser?: boolean, _needsPositionStickyOnElement?: boolean); _addStickyStyle(element: HTMLElement, dir: StickyDirection, dirValue: number): void; _getCalculatedZIndex(element: HTMLElement): string; _getCellWidths(row: HTMLElement, recalculateCellWidths?: boolean): number[];