diff --git a/src/cdk/table/row.ts b/src/cdk/table/row.ts index 31e7379cb9d4..067e294edfe7 100644 --- a/src/cdk/table/row.ts +++ b/src/cdk/table/row.ts @@ -18,7 +18,7 @@ import { SimpleChanges, TemplateRef, ViewContainerRef, - ViewEncapsulation, + ViewEncapsulation } from '@angular/core'; import {CanStick, CanStickCtor, mixinHasStickyInput} from './can-stick'; import {CdkCellDef, CdkColumnDef} from './cell'; @@ -40,8 +40,9 @@ export abstract class BaseRowDef implements OnChanges { /** Differ used to check if any changes were made to the columns. */ protected _columnsDiffer: IterableDiffer; - constructor(/** @docs-private */ public template: TemplateRef, - protected _differs: IterableDiffers) { } + constructor( + /** @docs-private */ public template: TemplateRef, protected _differs: IterableDiffers) { + } ngOnChanges(changes: SimpleChanges): void { // Create a new columns differ if one does not yet exist. Initialize it based on initial value @@ -57,7 +58,7 @@ export abstract class BaseRowDef implements OnChanges { * Returns the difference between the current columns and the columns from the last diff, or null * if there is no difference. */ - getColumnsDiff(): IterableChanges | null { + getColumnsDiff(): IterableChanges|null { return this._columnsDiffer.diff(this.columns); } @@ -65,7 +66,8 @@ export abstract class BaseRowDef implements OnChanges { extractCellTemplate(column: CdkColumnDef): TemplateRef { if (this instanceof CdkHeaderRowDef) { return column.headerCell.template; - } if (this instanceof CdkFooterRowDef) { + } + if (this instanceof CdkFooterRowDef) { return column.footerCell.template; } else { return column.cell.template; @@ -76,7 +78,7 @@ export abstract class BaseRowDef implements OnChanges { // Boilerplate for applying mixins to CdkHeaderRowDef. /** @docs-private */ export class CdkHeaderRowDefBase extends BaseRowDef {} -export const _CdkHeaderRowDefBase: CanStickCtor & typeof CdkHeaderRowDefBase = +export const _CdkHeaderRowDefBase: CanStickCtor&typeof CdkHeaderRowDefBase = mixinHasStickyInput(CdkHeaderRowDefBase); /** @@ -102,7 +104,7 @@ export class CdkHeaderRowDef extends _CdkHeaderRowDefBase implements CanStick, O // Boilerplate for applying mixins to CdkFooterRowDef. /** @docs-private */ export class CdkFooterRowDefBase extends BaseRowDef {} -export const _CdkFooterRowDefBase: CanStickCtor & typeof CdkFooterRowDefBase = +export const _CdkFooterRowDefBase: CanStickCtor&typeof CdkFooterRowDefBase = mixinHasStickyInput(CdkFooterRowDefBase); /** @@ -224,7 +226,7 @@ export class CdkCellOutlet implements OnDestroy { * a handle to provide that component's cells and context. After init, the CdkCellOutlet will * construct the cells with the provided context. */ - static mostRecentCellOutlet: CdkCellOutlet | null = null; + static mostRecentCellOutlet: CdkCellOutlet|null = null; constructor(public _viewContainer: ViewContainerRef) { CdkCellOutlet.mostRecentCellOutlet = this; @@ -248,10 +250,13 @@ export class CdkCellOutlet implements OnDestroy { 'class': 'cdk-header-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, }) -export class CdkHeaderRow { } +export class CdkHeaderRow { +} /** Footer template container that contains the cell outlet. Adds the right class and role. */ @@ -263,10 +268,13 @@ export class CdkHeaderRow { } 'class': 'cdk-footer-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, }) -export class CdkFooterRow { } +export class CdkFooterRow { +} /** Data row template container that contains the cell outlet. Adds the right class and role. */ @Component({ @@ -277,7 +285,10 @@ export class CdkFooterRow { } 'class': 'cdk-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, }) -export class CdkRow { } +export class CdkRow { +} diff --git a/src/cdk/table/table.ts b/src/cdk/table/table.ts index 50cabf656b35..35b21e0c7cdb 100644 --- a/src/cdk/table/table.ts +++ b/src/cdk/table/table.ts @@ -6,7 +6,11 @@ * found in the LICENSE file at https://angular.io/license */ +import {Direction, Directionality} from '@angular/cdk/bidi'; +import {coerceBooleanProperty} from '@angular/cdk/coercion'; import {CollectionViewer, DataSource, isDataSource} from '@angular/cdk/collections'; +import {Platform} from '@angular/cdk/platform'; +import {DOCUMENT} from '@angular/common'; import { AfterContentChecked, Attribute, @@ -17,6 +21,7 @@ import { Directive, ElementRef, EmbeddedViewRef, + Inject, Input, isDevMode, IterableChangeRecord, @@ -30,10 +35,8 @@ import { TrackByFunction, ViewChild, ViewContainerRef, - ViewEncapsulation, - Inject, + ViewEncapsulation } from '@angular/core'; -import {DOCUMENT} from '@angular/common'; import {BehaviorSubject, Observable, of as observableOf, Subject, Subscription} from 'rxjs'; import {takeUntil} from 'rxjs/operators'; import {CdkColumnDef} from './cell'; @@ -46,6 +49,7 @@ import { CdkHeaderRowDef, CdkRowDef } from './row'; +import {StickyStyler} from './sticky-styler'; import { getTableDuplicateColumnNameError, getTableMissingMatchingRowDefError, @@ -54,10 +58,6 @@ import { getTableUnknownColumnError, getTableUnknownDataSourceError } from './table-errors'; -import {coerceBooleanProperty} from '@angular/cdk/coercion'; -import {StickyStyler} from './sticky-styler'; -import {Direction, Directionality} from '@angular/cdk/bidi'; -import {Platform} from '@angular/cdk/platform'; /** Interface used to provide an outlet for rows to be inserted into. */ export interface RowOutlet { @@ -68,8 +68,8 @@ export interface RowOutlet { * Union of the types that can be set as the data source for a `CdkTable`. * @docs-private */ -type CdkTableDataSourceInput = DataSource | Observable | T[]> | - ReadonlyArray | T[]; +type CdkTableDataSourceInput = + DataSource|Observable|T[]>|ReadonlyArray|T[]; /** * Provides a handle for the table to grab the view container's ng-container to insert data rows. @@ -77,8 +77,7 @@ type CdkTableDataSourceInput = DataSource | Observable | */ @Directive({selector: '[rowOutlet]'}) export class DataRowOutlet implements RowOutlet { - constructor(public viewContainer: ViewContainerRef, - public elementRef: ElementRef) { } + constructor(public viewContainer: ViewContainerRef, public elementRef: ElementRef) {} } /** @@ -87,8 +86,7 @@ export class DataRowOutlet implements RowOutlet { */ @Directive({selector: '[headerRowOutlet]'}) export class HeaderRowOutlet implements RowOutlet { - constructor(public viewContainer: ViewContainerRef, - public elementRef: ElementRef) { } + constructor(public viewContainer: ViewContainerRef, public elementRef: ElementRef) {} } /** @@ -97,8 +95,7 @@ export class HeaderRowOutlet implements RowOutlet { */ @Directive({selector: '[footerRowOutlet]'}) export class FooterRowOutlet implements RowOutlet { - constructor(public viewContainer: ViewContainerRef, - public elementRef: ElementRef) { } + constructor(public viewContainer: ViewContainerRef, public elementRef: ElementRef) {} } /** @@ -107,9 +104,9 @@ export class FooterRowOutlet implements RowOutlet { * @docs-private */ export const CDK_TABLE_TEMPLATE = -// Note that according to MDN, the `caption` element has to be projected as the **first** element -// in the table. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption -` + // Note that according to MDN, the `caption` element has to be projected as the **first** + // element in the table. See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/caption + ` @@ -120,14 +117,14 @@ export const CDK_TABLE_TEMPLATE = * Interface used to conveniently type the possible context interfaces for the render row. * @docs-private */ -export interface RowContext - extends CdkCellOutletMultiRowContext, CdkCellOutletRowContext { } +export interface RowContext extends CdkCellOutletMultiRowContext, + CdkCellOutletRowContext {} /** * Class used to conveniently type the embedded view ref for rows with a context. * @docs-private */ -abstract class RowViewRef extends EmbeddedViewRef> { } +abstract class RowViewRef extends EmbeddedViewRef> {} /** * Set of properties that represents the identity of a single rendered row. @@ -163,13 +160,17 @@ export interface RenderRow { 'class': 'cdk-table', }, encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, + // The "OnPush" status for the `MatTable` component is effectively a noop, so we are removing it. + // The view for `MatTable` consists entirely of templates declared in other views. As they are + // declared elsewhere, they are checked when their declaration points are checked. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, }) export class CdkTable implements AfterContentChecked, CollectionViewer, OnDestroy, OnInit { private _document: Document; /** Latest data provided by the data source. */ - protected _data: T[] | ReadonlyArray; + protected _data: T[]|ReadonlyArray; /** Subject that emits when the component has been destroyed. */ private _onDestroy = new Subject(); @@ -178,14 +179,14 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes private _renderRows: RenderRow[]; /** Subscription that listens for the data provided by the data source. */ - private _renderChangeSubscription: Subscription | null; + private _renderChangeSubscription: Subscription|null; /** * Map of all the user's defined columns (header, data, and footer cell template) identified by * name. Collection populated by the column definitions gathered by `ContentChildren` as well as * any custom column definitions added to `_customColumnDefs`. */ - private _columnDefsByName = new Map(); + private _columnDefsByName = new Map(); /** * Set of all row definitions that can be used by this table. Populated by the rows gathered by @@ -211,7 +212,7 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes private _dataDiffer: IterableDiffer>; /** Stores the row definition that does not have a when predicate. */ - private _defaultRowDef: CdkRowDef | null; + private _defaultRowDef: CdkRowDef|null; /** * Column definitions that were defined outside of the direct content children of the table. @@ -290,12 +291,13 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes * Accepts a function that takes two parameters, `index` and `item`. */ @Input() - get trackBy(): TrackByFunction { return this._trackByFn; } + get trackBy(): TrackByFunction { + return this._trackByFn; + } set trackBy(fn: TrackByFunction) { - if (isDevMode() && - fn != null && typeof fn !== 'function' && - console && console.warn) { - console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`); + if (isDevMode() && fn != null && typeof fn !== 'function' && console && + console.warn) { + console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`); } this._trackByFn = fn; } @@ -322,7 +324,9 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes * subscriptions registered during the connect process). */ @Input() - get dataSource(): CdkTableDataSourceInput { return this._dataSource; } + get dataSource(): CdkTableDataSourceInput { + return this._dataSource; + } set dataSource(dataSource: CdkTableDataSourceInput) { if (this._dataSource !== dataSource) { this._switchDataSource(dataSource); @@ -337,7 +341,9 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes * defined in the table, or otherwise the default row which does not have a when predicate. */ @Input() - get multiTemplateDataRows(): boolean { return this._multiTemplateDataRows; } + get multiTemplateDataRows(): boolean { + return this._multiTemplateDataRows; + } set multiTemplateDataRows(v: boolean) { this._multiTemplateDataRows = coerceBooleanProperty(v); if (this._rowOutlet.viewContainer.length) { @@ -375,18 +381,17 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes /** Set of footer row definitions that were provided to the table as content children. */ @ContentChildren(CdkFooterRowDef) _contentFooterRowDefs: QueryList; - constructor(protected readonly _differs: IterableDiffers, - protected readonly _changeDetectorRef: ChangeDetectorRef, - protected readonly _elementRef: ElementRef, - @Attribute('role') role: string, - @Optional() protected readonly _dir: Directionality, - /** - * @deprecated - * @breaking-change 8.0.0 `_document` and `_platform` to - * be made into a required parameters. - */ - @Inject(DOCUMENT) _document?: any, - private _platform?: Platform) { + constructor( + protected readonly _differs: IterableDiffers, + protected readonly _changeDetectorRef: ChangeDetectorRef, + protected readonly _elementRef: ElementRef, @Attribute('role') role: string, + @Optional() protected readonly _dir: Directionality, + /** + * @deprecated + * @breaking-change 8.0.0 `_document` and `_platform` to + * be made into a required parameters. + */ + @Inject(DOCUMENT) _document?: any, private _platform?: Platform) { if (!role) { this._elementRef.nativeElement.setAttribute('role', 'grid'); } @@ -472,22 +477,24 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes renderRows() { this._renderRows = this._getAllRenderRows(); const changes = this._dataDiffer.diff(this._renderRows); - if (!changes) { return; } + if (!changes) { + return; + } const viewContainer = this._rowOutlet.viewContainer; - changes.forEachOperation((record: IterableChangeRecord>, - prevIndex: number | null, - currentIndex: number | null) => { - if (record.previousIndex == null) { - this._insertRow(record.item, currentIndex!); - } else if (currentIndex == null) { - viewContainer.remove(prevIndex!); - } else { - const view = >viewContainer.get(prevIndex!); - viewContainer.move(view!, currentIndex); - } - }); + changes.forEachOperation( + (record: IterableChangeRecord>, prevIndex: number|null, + currentIndex: number|null) => { + if (record.previousIndex == null) { + this._insertRow(record.item, currentIndex!); + } else if (currentIndex == null) { + viewContainer.remove(prevIndex!); + } else { + const view = >viewContainer.get(prevIndex!); + viewContainer.move(view!, currentIndex); + } + }); // Update the meta context of a row's context data (index, count, first, last, ...) this._updateRowIndexContext(); @@ -750,8 +757,7 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes mergeQueryListAndSet(this._contentHeaderRowDefs, this._customHeaderRowDefs); this._footerRowDefs = mergeQueryListAndSet(this._contentFooterRowDefs, this._customFooterRowDefs); - this._rowDefs = - mergeQueryListAndSet(this._contentRowDefs, this._customRowDefs); + this._rowDefs = mergeQueryListAndSet(this._contentRowDefs, this._customRowDefs); // After all row definitions are determined, find the row definition to be considered default. const defaultRowDefs = this._rowDefs.filter(def => !def.when); @@ -815,9 +821,11 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes /** Set up a subscription for the data provided by the data source. */ private _observeRenderChanges() { // If no data source has been set, there is nothing to observe for changes. - if (!this.dataSource) { return; } + if (!this.dataSource) { + return; + } - let dataStream: Observable> | undefined; + let dataStream: Observable>|undefined; if (isDataSource(this.dataSource)) { dataStream = this.dataSource.connect(this); @@ -831,12 +839,10 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes throw getTableUnknownDataSourceError(); } - this._renderChangeSubscription = dataStream - .pipe(takeUntil(this._onDestroy)) - .subscribe(data => { - this._data = data || []; - this.renderRows(); - }); + this._renderChangeSubscription = dataStream.pipe(takeUntil(this._onDestroy)).subscribe(data => { + this._data = data || []; + this.renderRows(); + }); } /** @@ -901,7 +907,9 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes * definition. */ _getRowDefs(data: T, dataIndex: number): CdkRowDef[] { - if (this._rowDefs.length == 1) { return [this._rowDefs[0]]; } + if (this._rowDefs.length == 1) { + return [this._rowDefs[0]]; + } let rowDefs: CdkRowDef[] = []; if (this.multiTemplateDataRows) { @@ -976,7 +984,9 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes /** Gets the column definitions for the provided row def. */ private _getCellTemplates(rowDef: BaseRowDef): TemplateRef[] { - if (!rowDef || !rowDef.columns) { return []; } + if (!rowDef || !rowDef.columns) { + return []; + } return Array.from(rowDef.columns, columnId => { const column = this._columnDefsByName.get(columnId); @@ -1056,7 +1066,8 @@ export class CdkTable implements AfterContentChecked, CollectionViewer, OnDes */ private _setupStickyStyler() { const direction: Direction = this._dir ? this._dir.value : 'ltr'; - this._stickyStyler = new StickyStyler(this._isNativeHtmlTable, + this._stickyStyler = new StickyStyler( + this._isNativeHtmlTable, // @breaking-change 8.0.0 remove the null check for `this._platform`. this.stickyCssClass, direction, this._platform ? this._platform.isBrowser : true); (this._dir ? this._dir.change : observableOf()) diff --git a/src/lib/table/row.ts b/src/lib/table/row.ts index 2c1f3f0b320a..000a786f9531 100644 --- a/src/lib/table/row.ts +++ b/src/lib/table/row.ts @@ -7,18 +7,15 @@ */ import { - ChangeDetectionStrategy, - Component, - Directive, - ViewEncapsulation -} from '@angular/core'; -import { - CDK_ROW_TEMPLATE, CdkFooterRow, CdkFooterRowDef, + CDK_ROW_TEMPLATE, + CdkFooterRow, + CdkFooterRowDef, CdkHeaderRow, CdkHeaderRowDef, CdkRow, - CdkRowDef, + CdkRowDef } from '@angular/cdk/table'; +import {ChangeDetectionStrategy, Component, Directive, ViewEncapsulation} from '@angular/core'; /** * Header row definition for the mat-table. @@ -29,7 +26,8 @@ import { providers: [{provide: CdkHeaderRowDef, useExisting: MatHeaderRowDef}], inputs: ['columns: matHeaderRowDef', 'sticky: matHeaderRowDefSticky'], }) -export class MatHeaderRowDef extends CdkHeaderRowDef {} +export class MatHeaderRowDef extends CdkHeaderRowDef { +} /** * Footer row definition for the mat-table. @@ -40,7 +38,8 @@ export class MatHeaderRowDef extends CdkHeaderRowDef {} providers: [{provide: CdkFooterRowDef, useExisting: MatFooterRowDef}], inputs: ['columns: matFooterRowDef', 'sticky: matFooterRowDefSticky'], }) -export class MatFooterRowDef extends CdkFooterRowDef {} +export class MatFooterRowDef extends CdkFooterRowDef { +} /** * Data row definition for the mat-table. @@ -52,7 +51,8 @@ export class MatFooterRowDef extends CdkFooterRowDef {} providers: [{provide: CdkRowDef, useExisting: MatRowDef}], inputs: ['columns: matRowDefColumns', 'when: matRowDefWhen'], }) -export class MatRowDef extends CdkRowDef {} +export class MatRowDef extends CdkRowDef { +} /** Footer template container that contains the cell outlet. Adds the right class and role. */ @Component({ @@ -63,12 +63,15 @@ export class MatRowDef extends CdkRowDef {} 'class': 'mat-header-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, exportAs: 'matHeaderRow', providers: [{provide: CdkHeaderRow, useExisting: MatHeaderRow}], }) -export class MatHeaderRow extends CdkHeaderRow { } +export class MatHeaderRow extends CdkHeaderRow { +} /** Footer template container that contains the cell outlet. Adds the right class and role. */ @Component({ @@ -79,12 +82,15 @@ export class MatHeaderRow extends CdkHeaderRow { } 'class': 'mat-footer-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, exportAs: 'matFooterRow', providers: [{provide: CdkFooterRow, useExisting: MatFooterRow}], }) -export class MatFooterRow extends CdkFooterRow { } +export class MatFooterRow extends CdkFooterRow { +} /** Data row template container that contains the cell outlet. Adds the right class and role. */ @Component({ @@ -95,9 +101,12 @@ export class MatFooterRow extends CdkFooterRow { } 'class': 'mat-row', 'role': 'row', }, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, exportAs: 'matRow', providers: [{provide: CdkRow, useExisting: MatRow}], }) -export class MatRow extends CdkRow { } +export class MatRow extends CdkRow { +} diff --git a/src/lib/table/table.ts b/src/lib/table/table.ts index d6acb8649934..8aa93eede9f3 100644 --- a/src/lib/table/table.ts +++ b/src/lib/table/table.ts @@ -22,7 +22,9 @@ import {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/co 'class': 'mat-table', }, encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, + // See note on CdkTable for explanation on why this uses the default change detection strategy. + // tslint:disable-next-line:validate-decorators + changeDetection: ChangeDetectionStrategy.Default, }) export class MatTable extends CdkTable { /** Overrides the sticky CSS class set by the `CdkTable`. */ diff --git a/tools/public_api_guard/cdk/table.d.ts b/tools/public_api_guard/cdk/table.d.ts index cb14dade32c1..d2e7e699e1b1 100644 --- a/tools/public_api_guard/cdk/table.d.ts +++ b/tools/public_api_guard/cdk/table.d.ts @@ -11,9 +11,8 @@ export declare class BaseCdkCell { export declare abstract class BaseRowDef implements OnChanges { protected _columnsDiffer: IterableDiffer; protected _differs: IterableDiffers; - columns: Iterable; - template: TemplateRef; - constructor(/** @docs-private */ template: TemplateRef, _differs: IterableDiffers); + columns: Iterable; template: TemplateRef; + constructor( template: TemplateRef, _differs: IterableDiffers); extractCellTemplate(column: CdkColumnDef): TemplateRef; getColumnsDiff(): IterableChanges | null; ngOnChanges(changes: SimpleChanges): void;