UNPKG

@angular/cdk

Version:

Angular Material Component Development Kit

1,777 lines (1,770 loc) 73.2 kB
import { isDataSource } from './_data-source-chunk.mjs'; export { DataSource } from './_data-source-chunk.mjs'; import * as i0 from '@angular/core'; import { InjectionToken, inject, TemplateRef, Directive, booleanAttribute, Input, ContentChild, ElementRef, IterableDiffers, ViewContainerRef, Component, ChangeDetectionStrategy, ViewEncapsulation, afterNextRender, ChangeDetectorRef, DOCUMENT, EventEmitter, Injector, HostAttributeToken, Output, ContentChildren, ViewChild, NgModule } from '@angular/core'; import { Subject, BehaviorSubject, isObservable, of } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { _VIEW_REPEATER_STRATEGY, _RecycleViewRepeaterStrategy, _ViewRepeaterOperation } from './_recycle-view-repeater-strategy-chunk.mjs'; import { _DisposeViewRepeaterStrategy } from './_dispose-view-repeater-strategy-chunk.mjs'; import { Directionality } from './_directionality-chunk.mjs'; import { Platform } from './_platform-chunk.mjs'; import { ViewportRuler, ScrollingModule } from './scrolling.mjs'; import '@angular/common'; import './_element-chunk.mjs'; import './_scrolling-chunk.mjs'; import './bidi.mjs'; const CDK_TABLE = new InjectionToken('CDK_TABLE'); const TEXT_COLUMN_OPTIONS = new InjectionToken('text-column-options'); class CdkCellDef { template = inject(TemplateRef); constructor() {} static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCellDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkCellDef, isStandalone: true, selector: "[cdkCellDef]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCellDef, decorators: [{ type: Directive, args: [{ selector: '[cdkCellDef]' }] }], ctorParameters: () => [] }); class CdkHeaderCellDef { template = inject(TemplateRef); constructor() {} static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderCellDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkHeaderCellDef, isStandalone: true, selector: "[cdkHeaderCellDef]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderCellDef, decorators: [{ type: Directive, args: [{ selector: '[cdkHeaderCellDef]' }] }], ctorParameters: () => [] }); class CdkFooterCellDef { template = inject(TemplateRef); constructor() {} static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterCellDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkFooterCellDef, isStandalone: true, selector: "[cdkFooterCellDef]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterCellDef, decorators: [{ type: Directive, args: [{ selector: '[cdkFooterCellDef]' }] }], ctorParameters: () => [] }); class CdkColumnDef { _table = inject(CDK_TABLE, { optional: true }); _hasStickyChanged = false; get name() { return this._name; } set name(name) { this._setNameInput(name); } _name; get sticky() { return this._sticky; } set sticky(value) { if (value !== this._sticky) { this._sticky = value; this._hasStickyChanged = true; } } _sticky = false; get stickyEnd() { return this._stickyEnd; } set stickyEnd(value) { if (value !== this._stickyEnd) { this._stickyEnd = value; this._hasStickyChanged = true; } } _stickyEnd = false; cell; headerCell; footerCell; cssClassFriendlyName; _columnCssClassName; constructor() {} hasStickyChanged() { const hasStickyChanged = this._hasStickyChanged; this.resetStickyChanged(); return hasStickyChanged; } resetStickyChanged() { this._hasStickyChanged = false; } _updateColumnCssClassName() { this._columnCssClassName = [`cdk-column-${this.cssClassFriendlyName}`]; } _setNameInput(value) { if (value) { this._name = value; this.cssClassFriendlyName = value.replace(/[^a-z0-9_-]/gi, '-'); this._updateColumnCssClassName(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkColumnDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.0.0", type: CdkColumnDef, isStandalone: true, selector: "[cdkColumnDef]", inputs: { name: ["cdkColumnDef", "name"], sticky: ["sticky", "sticky", booleanAttribute], stickyEnd: ["stickyEnd", "stickyEnd", booleanAttribute] }, providers: [{ provide: 'MAT_SORT_HEADER_COLUMN_DEF', useExisting: CdkColumnDef }], queries: [{ propertyName: "cell", first: true, predicate: CdkCellDef, descendants: true }, { propertyName: "headerCell", first: true, predicate: CdkHeaderCellDef, descendants: true }, { propertyName: "footerCell", first: true, predicate: CdkFooterCellDef, descendants: true }], ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkColumnDef, decorators: [{ type: Directive, args: [{ selector: '[cdkColumnDef]', providers: [{ provide: 'MAT_SORT_HEADER_COLUMN_DEF', useExisting: CdkColumnDef }] }] }], ctorParameters: () => [], propDecorators: { name: [{ type: Input, args: ['cdkColumnDef'] }], sticky: [{ type: Input, args: [{ transform: booleanAttribute }] }], stickyEnd: [{ type: Input, args: [{ transform: booleanAttribute }] }], cell: [{ type: ContentChild, args: [CdkCellDef] }], headerCell: [{ type: ContentChild, args: [CdkHeaderCellDef] }], footerCell: [{ type: ContentChild, args: [CdkFooterCellDef] }] } }); class BaseCdkCell { constructor(columnDef, elementRef) { elementRef.nativeElement.classList.add(...columnDef._columnCssClassName); } } class CdkHeaderCell extends BaseCdkCell { constructor() { super(inject(CdkColumnDef), inject(ElementRef)); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderCell, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkHeaderCell, isStandalone: true, selector: "cdk-header-cell, th[cdk-header-cell]", host: { attributes: { "role": "columnheader" }, classAttribute: "cdk-header-cell" }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderCell, decorators: [{ type: Directive, args: [{ selector: 'cdk-header-cell, th[cdk-header-cell]', host: { 'class': 'cdk-header-cell', 'role': 'columnheader' } }] }], ctorParameters: () => [] }); class CdkFooterCell extends BaseCdkCell { constructor() { const columnDef = inject(CdkColumnDef); const elementRef = inject(ElementRef); super(columnDef, elementRef); const role = columnDef._table?._getCellRole(); if (role) { elementRef.nativeElement.setAttribute('role', role); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterCell, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkFooterCell, isStandalone: true, selector: "cdk-footer-cell, td[cdk-footer-cell]", host: { classAttribute: "cdk-footer-cell" }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterCell, decorators: [{ type: Directive, args: [{ selector: 'cdk-footer-cell, td[cdk-footer-cell]', host: { 'class': 'cdk-footer-cell' } }] }], ctorParameters: () => [] }); class CdkCell extends BaseCdkCell { constructor() { const columnDef = inject(CdkColumnDef); const elementRef = inject(ElementRef); super(columnDef, elementRef); const role = columnDef._table?._getCellRole(); if (role) { elementRef.nativeElement.setAttribute('role', role); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCell, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkCell, isStandalone: true, selector: "cdk-cell, td[cdk-cell]", host: { classAttribute: "cdk-cell" }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCell, decorators: [{ type: Directive, args: [{ selector: 'cdk-cell, td[cdk-cell]', host: { 'class': 'cdk-cell' } }] }], ctorParameters: () => [] }); const CDK_ROW_TEMPLATE = `<ng-container cdkCellOutlet></ng-container>`; class BaseRowDef { template = inject(TemplateRef); _differs = inject(IterableDiffers); columns; _columnsDiffer; constructor() {} ngOnChanges(changes) { if (!this._columnsDiffer) { const columns = changes['columns'] && changes['columns'].currentValue || []; this._columnsDiffer = this._differs.find(columns).create(); this._columnsDiffer.diff(columns); } } getColumnsDiff() { return this._columnsDiffer.diff(this.columns); } extractCellTemplate(column) { if (this instanceof CdkHeaderRowDef) { return column.headerCell.template; } if (this instanceof CdkFooterRowDef) { return column.footerCell.template; } else { return column.cell.template; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: BaseRowDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: BaseRowDef, isStandalone: true, usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: BaseRowDef, decorators: [{ type: Directive }], ctorParameters: () => [] }); class CdkHeaderRowDef extends BaseRowDef { _table = inject(CDK_TABLE, { optional: true }); _hasStickyChanged = false; get sticky() { return this._sticky; } set sticky(value) { if (value !== this._sticky) { this._sticky = value; this._hasStickyChanged = true; } } _sticky = false; constructor() { super(inject(TemplateRef), inject(IterableDiffers)); } ngOnChanges(changes) { super.ngOnChanges(changes); } hasStickyChanged() { const hasStickyChanged = this._hasStickyChanged; this.resetStickyChanged(); return hasStickyChanged; } resetStickyChanged() { this._hasStickyChanged = false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderRowDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.0.0", type: CdkHeaderRowDef, isStandalone: true, selector: "[cdkHeaderRowDef]", inputs: { columns: ["cdkHeaderRowDef", "columns"], sticky: ["cdkHeaderRowDefSticky", "sticky", booleanAttribute] }, usesInheritance: true, usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderRowDef, decorators: [{ type: Directive, args: [{ selector: '[cdkHeaderRowDef]', inputs: [{ name: 'columns', alias: 'cdkHeaderRowDef' }] }] }], ctorParameters: () => [], propDecorators: { sticky: [{ type: Input, args: [{ alias: 'cdkHeaderRowDefSticky', transform: booleanAttribute }] }] } }); class CdkFooterRowDef extends BaseRowDef { _table = inject(CDK_TABLE, { optional: true }); _hasStickyChanged = false; get sticky() { return this._sticky; } set sticky(value) { if (value !== this._sticky) { this._sticky = value; this._hasStickyChanged = true; } } _sticky = false; constructor() { super(inject(TemplateRef), inject(IterableDiffers)); } ngOnChanges(changes) { super.ngOnChanges(changes); } hasStickyChanged() { const hasStickyChanged = this._hasStickyChanged; this.resetStickyChanged(); return hasStickyChanged; } resetStickyChanged() { this._hasStickyChanged = false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterRowDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "21.0.0", type: CdkFooterRowDef, isStandalone: true, selector: "[cdkFooterRowDef]", inputs: { columns: ["cdkFooterRowDef", "columns"], sticky: ["cdkFooterRowDefSticky", "sticky", booleanAttribute] }, usesInheritance: true, usesOnChanges: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterRowDef, decorators: [{ type: Directive, args: [{ selector: '[cdkFooterRowDef]', inputs: [{ name: 'columns', alias: 'cdkFooterRowDef' }] }] }], ctorParameters: () => [], propDecorators: { sticky: [{ type: Input, args: [{ alias: 'cdkFooterRowDefSticky', transform: booleanAttribute }] }] } }); class CdkRowDef extends BaseRowDef { _table = inject(CDK_TABLE, { optional: true }); when; constructor() { super(inject(TemplateRef), inject(IterableDiffers)); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRowDef, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkRowDef, isStandalone: true, selector: "[cdkRowDef]", inputs: { columns: ["cdkRowDefColumns", "columns"], when: ["cdkRowDefWhen", "when"] }, usesInheritance: true, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRowDef, decorators: [{ type: Directive, args: [{ selector: '[cdkRowDef]', inputs: [{ name: 'columns', alias: 'cdkRowDefColumns' }, { name: 'when', alias: 'cdkRowDefWhen' }] }] }], ctorParameters: () => [] }); class CdkCellOutlet { _viewContainer = inject(ViewContainerRef); cells; context; static mostRecentCellOutlet = null; constructor() { CdkCellOutlet.mostRecentCellOutlet = this; } ngOnDestroy() { if (CdkCellOutlet.mostRecentCellOutlet === this) { CdkCellOutlet.mostRecentCellOutlet = null; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCellOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkCellOutlet, isStandalone: true, selector: "[cdkCellOutlet]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkCellOutlet, decorators: [{ type: Directive, args: [{ selector: '[cdkCellOutlet]' }] }], ctorParameters: () => [] }); class CdkHeaderRow { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: CdkHeaderRow, isStandalone: true, selector: "cdk-header-row, tr[cdk-header-row]", host: { attributes: { "role": "row" }, classAttribute: "cdk-header-row" }, ngImport: i0, template: "<ng-container cdkCellOutlet></ng-container>", isInline: true, dependencies: [{ kind: "directive", type: CdkCellOutlet, selector: "[cdkCellOutlet]" }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkHeaderRow, decorators: [{ type: Component, args: [{ selector: 'cdk-header-row, tr[cdk-header-row]', template: CDK_ROW_TEMPLATE, host: { 'class': 'cdk-header-row', 'role': 'row' }, changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, imports: [CdkCellOutlet] }] }] }); class CdkFooterRow { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: CdkFooterRow, isStandalone: true, selector: "cdk-footer-row, tr[cdk-footer-row]", host: { attributes: { "role": "row" }, classAttribute: "cdk-footer-row" }, ngImport: i0, template: "<ng-container cdkCellOutlet></ng-container>", isInline: true, dependencies: [{ kind: "directive", type: CdkCellOutlet, selector: "[cdkCellOutlet]" }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkFooterRow, decorators: [{ type: Component, args: [{ selector: 'cdk-footer-row, tr[cdk-footer-row]', template: CDK_ROW_TEMPLATE, host: { 'class': 'cdk-footer-row', 'role': 'row' }, changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, imports: [CdkCellOutlet] }] }] }); class CdkRow { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRow, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.0", type: CdkRow, isStandalone: true, selector: "cdk-row, tr[cdk-row]", host: { attributes: { "role": "row" }, classAttribute: "cdk-row" }, ngImport: i0, template: "<ng-container cdkCellOutlet></ng-container>", isInline: true, dependencies: [{ kind: "directive", type: CdkCellOutlet, selector: "[cdkCellOutlet]" }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRow, decorators: [{ type: Component, args: [{ selector: 'cdk-row, tr[cdk-row]', template: CDK_ROW_TEMPLATE, host: { 'class': 'cdk-row', 'role': 'row' }, changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, imports: [CdkCellOutlet] }] }] }); class CdkNoDataRow { templateRef = inject(TemplateRef); _contentClassNames = ['cdk-no-data-row', 'cdk-row']; _cellClassNames = ['cdk-cell', 'cdk-no-data-cell']; _cellSelector = 'td, cdk-cell, [cdk-cell], .cdk-cell'; constructor() {} static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkNoDataRow, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkNoDataRow, isStandalone: true, selector: "ng-template[cdkNoDataRow]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkNoDataRow, decorators: [{ type: Directive, args: [{ selector: 'ng-template[cdkNoDataRow]' }] }], ctorParameters: () => [] }); const STICKY_DIRECTIONS = ['top', 'bottom', 'left', 'right']; class StickyStyler { _isNativeHtmlTable; _stickCellCss; _isBrowser; _needsPositionStickyOnElement; direction; _positionListener; _tableInjector; _elemSizeCache = new WeakMap(); _resizeObserver = globalThis?.ResizeObserver ? new globalThis.ResizeObserver(entries => this._updateCachedSizes(entries)) : null; _updatedStickyColumnsParamsToReplay = []; _stickyColumnsReplayTimeout = null; _cachedCellWidths = []; _borderCellCss; _destroyed = false; constructor(_isNativeHtmlTable, _stickCellCss, _isBrowser = true, _needsPositionStickyOnElement = true, direction, _positionListener, _tableInjector) { this._isNativeHtmlTable = _isNativeHtmlTable; this._stickCellCss = _stickCellCss; this._isBrowser = _isBrowser; this._needsPositionStickyOnElement = _needsPositionStickyOnElement; this.direction = direction; this._positionListener = _positionListener; this._tableInjector = _tableInjector; this._borderCellCss = { 'top': `${_stickCellCss}-border-elem-top`, 'bottom': `${_stickCellCss}-border-elem-bottom`, 'left': `${_stickCellCss}-border-elem-left`, 'right': `${_stickCellCss}-border-elem-right` }; } clearStickyPositioning(rows, stickyDirections) { if (stickyDirections.includes('left') || stickyDirections.includes('right')) { this._removeFromStickyColumnReplayQueue(rows); } const elementsToClear = []; for (const row of rows) { if (row.nodeType !== row.ELEMENT_NODE) { continue; } elementsToClear.push(row, ...Array.from(row.children)); } afterNextRender({ write: () => { for (const element of elementsToClear) { this._removeStickyStyle(element, stickyDirections); } } }, { injector: this._tableInjector }); } updateStickyColumns(rows, stickyStartStates, stickyEndStates, recalculateCellWidths = true, replay = true) { if (!rows.length || !this._isBrowser || !(stickyStartStates.some(state => state) || stickyEndStates.some(state => state))) { this._positionListener?.stickyColumnsUpdated({ sizes: [] }); this._positionListener?.stickyEndColumnsUpdated({ sizes: [] }); return; } const firstRow = rows[0]; const numCells = firstRow.children.length; const isRtl = this.direction === 'rtl'; const start = isRtl ? 'right' : 'left'; const end = isRtl ? 'left' : 'right'; const lastStickyStart = stickyStartStates.lastIndexOf(true); const firstStickyEnd = stickyEndStates.indexOf(true); let cellWidths; let startPositions; let endPositions; if (replay) { this._updateStickyColumnReplayQueue({ rows: [...rows], stickyStartStates: [...stickyStartStates], stickyEndStates: [...stickyEndStates] }); } afterNextRender({ earlyRead: () => { cellWidths = this._getCellWidths(firstRow, recalculateCellWidths); startPositions = this._getStickyStartColumnPositions(cellWidths, stickyStartStates); endPositions = this._getStickyEndColumnPositions(cellWidths, stickyEndStates); }, write: () => { for (const row of rows) { for (let i = 0; i < numCells; i++) { const cell = row.children[i]; if (stickyStartStates[i]) { this._addStickyStyle(cell, start, startPositions[i], i === lastStickyStart); } if (stickyEndStates[i]) { this._addStickyStyle(cell, end, endPositions[i], i === firstStickyEnd); } } } if (this._positionListener && cellWidths.some(w => !!w)) { this._positionListener.stickyColumnsUpdated({ sizes: lastStickyStart === -1 ? [] : cellWidths.slice(0, lastStickyStart + 1).map((width, index) => stickyStartStates[index] ? width : null) }); this._positionListener.stickyEndColumnsUpdated({ sizes: firstStickyEnd === -1 ? [] : cellWidths.slice(firstStickyEnd).map((width, index) => stickyEndStates[index + firstStickyEnd] ? width : null).reverse() }); } } }, { injector: this._tableInjector }); } stickRows(rowsToStick, stickyStates, position) { if (!this._isBrowser) { return; } const rows = position === 'bottom' ? rowsToStick.slice().reverse() : rowsToStick; const states = position === 'bottom' ? stickyStates.slice().reverse() : stickyStates; const stickyOffsets = []; const stickyCellHeights = []; const elementsToStick = []; afterNextRender({ earlyRead: () => { for (let rowIndex = 0, stickyOffset = 0; rowIndex < rows.length; rowIndex++) { if (!states[rowIndex]) { continue; } stickyOffsets[rowIndex] = stickyOffset; const row = rows[rowIndex]; elementsToStick[rowIndex] = this._isNativeHtmlTable ? Array.from(row.children) : [row]; const height = this._retrieveElementSize(row).height; stickyOffset += height; stickyCellHeights[rowIndex] = height; } }, write: () => { const borderedRowIndex = states.lastIndexOf(true); for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) { if (!states[rowIndex]) { continue; } const offset = stickyOffsets[rowIndex]; const isBorderedRowIndex = rowIndex === borderedRowIndex; for (const element of elementsToStick[rowIndex]) { this._addStickyStyle(element, position, offset, isBorderedRowIndex); } } if (position === 'top') { this._positionListener?.stickyHeaderRowsUpdated({ sizes: stickyCellHeights, offsets: stickyOffsets, elements: elementsToStick }); } else { this._positionListener?.stickyFooterRowsUpdated({ sizes: stickyCellHeights, offsets: stickyOffsets, elements: elementsToStick }); } } }, { injector: this._tableInjector }); } updateStickyFooterContainer(tableElement, stickyStates) { if (!this._isNativeHtmlTable) { return; } afterNextRender({ write: () => { const tfoot = tableElement.querySelector('tfoot'); if (tfoot) { if (stickyStates.some(state => !state)) { this._removeStickyStyle(tfoot, ['bottom']); } else { this._addStickyStyle(tfoot, 'bottom', 0, false); } } } }, { injector: this._tableInjector }); } destroy() { if (this._stickyColumnsReplayTimeout) { clearTimeout(this._stickyColumnsReplayTimeout); } this._resizeObserver?.disconnect(); this._destroyed = true; } _removeStickyStyle(element, stickyDirections) { if (!element.classList.contains(this._stickCellCss)) { return; } for (const dir of stickyDirections) { element.style[dir] = ''; element.classList.remove(this._borderCellCss[dir]); } const hasDirection = STICKY_DIRECTIONS.some(dir => stickyDirections.indexOf(dir) === -1 && element.style[dir]); if (hasDirection) { element.style.zIndex = this._getCalculatedZIndex(element); } else { element.style.zIndex = ''; if (this._needsPositionStickyOnElement) { element.style.position = ''; } element.classList.remove(this._stickCellCss); } } _addStickyStyle(element, dir, dirValue, isBorderElement) { element.classList.add(this._stickCellCss); if (isBorderElement) { element.classList.add(this._borderCellCss[dir]); } element.style[dir] = `${dirValue}px`; element.style.zIndex = this._getCalculatedZIndex(element); if (this._needsPositionStickyOnElement) { element.style.cssText += 'position: -webkit-sticky; position: sticky; '; } } _getCalculatedZIndex(element) { const zIndexIncrements = { top: 100, bottom: 10, left: 1, right: 1 }; let zIndex = 0; for (const dir of STICKY_DIRECTIONS) { if (element.style[dir]) { zIndex += zIndexIncrements[dir]; } } return zIndex ? `${zIndex}` : ''; } _getCellWidths(row, recalculateCellWidths = true) { if (!recalculateCellWidths && this._cachedCellWidths.length) { return this._cachedCellWidths; } const cellWidths = []; const firstRowCells = row.children; for (let i = 0; i < firstRowCells.length; i++) { const cell = firstRowCells[i]; cellWidths.push(this._retrieveElementSize(cell).width); } this._cachedCellWidths = cellWidths; return cellWidths; } _getStickyStartColumnPositions(widths, stickyStates) { const positions = []; let nextPosition = 0; for (let i = 0; i < widths.length; i++) { if (stickyStates[i]) { positions[i] = nextPosition; nextPosition += widths[i]; } } return positions; } _getStickyEndColumnPositions(widths, stickyStates) { const positions = []; let nextPosition = 0; for (let i = widths.length; i > 0; i--) { if (stickyStates[i]) { positions[i] = nextPosition; nextPosition += widths[i]; } } return positions; } _retrieveElementSize(element) { const cachedSize = this._elemSizeCache.get(element); if (cachedSize) { return cachedSize; } const clientRect = element.getBoundingClientRect(); const size = { width: clientRect.width, height: clientRect.height }; if (!this._resizeObserver) { return size; } this._elemSizeCache.set(element, size); this._resizeObserver.observe(element, { box: 'border-box' }); return size; } _updateStickyColumnReplayQueue(params) { this._removeFromStickyColumnReplayQueue(params.rows); if (!this._stickyColumnsReplayTimeout) { this._updatedStickyColumnsParamsToReplay.push(params); } } _removeFromStickyColumnReplayQueue(rows) { const rowsSet = new Set(rows); for (const update of this._updatedStickyColumnsParamsToReplay) { update.rows = update.rows.filter(row => !rowsSet.has(row)); } this._updatedStickyColumnsParamsToReplay = this._updatedStickyColumnsParamsToReplay.filter(update => !!update.rows.length); } _updateCachedSizes(entries) { let needsColumnUpdate = false; for (const entry of entries) { const newEntry = entry.borderBoxSize?.length ? { width: entry.borderBoxSize[0].inlineSize, height: entry.borderBoxSize[0].blockSize } : { width: entry.contentRect.width, height: entry.contentRect.height }; if (newEntry.width !== this._elemSizeCache.get(entry.target)?.width && isCell(entry.target)) { needsColumnUpdate = true; } this._elemSizeCache.set(entry.target, newEntry); } if (needsColumnUpdate && this._updatedStickyColumnsParamsToReplay.length) { if (this._stickyColumnsReplayTimeout) { clearTimeout(this._stickyColumnsReplayTimeout); } this._stickyColumnsReplayTimeout = setTimeout(() => { if (this._destroyed) { return; } for (const update of this._updatedStickyColumnsParamsToReplay) { this.updateStickyColumns(update.rows, update.stickyStartStates, update.stickyEndStates, true, false); } this._updatedStickyColumnsParamsToReplay = []; this._stickyColumnsReplayTimeout = null; }, 0); } } } function isCell(element) { return ['cdk-cell', 'cdk-header-cell', 'cdk-footer-cell'].some(klass => element.classList.contains(klass)); } function getTableUnknownColumnError(id) { return Error(`Could not find column with id "${id}".`); } function getTableDuplicateColumnNameError(name) { return Error(`Duplicate column definition name provided: "${name}".`); } function getTableMultipleDefaultRowDefsError() { return Error(`There can only be one default row without a when predicate function. ` + 'Or set `multiTemplateDataRows`.'); } function getTableMissingMatchingRowDefError(data) { return Error(`Could not find a matching row definition for the ` + `provided row data: ${JSON.stringify(data)}`); } function getTableMissingRowDefsError() { return Error('Missing definitions for header, footer, and row; ' + 'cannot determine which columns should be rendered.'); } function getTableUnknownDataSourceError() { return Error(`Provided data source did not match an array, Observable, or DataSource`); } function getTableTextColumnMissingParentTableError() { return Error(`Text column could not find a parent table for registration.`); } function getTableTextColumnMissingNameError() { return Error(`Table text column must have a name.`); } const STICKY_POSITIONING_LISTENER = new InjectionToken('CDK_SPL'); class CdkRecycleRows { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRecycleRows, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: CdkRecycleRows, isStandalone: true, selector: "cdk-table[recycleRows], table[cdk-table][recycleRows]", providers: [{ provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy }], ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: CdkRecycleRows, decorators: [{ type: Directive, args: [{ selector: 'cdk-table[recycleRows], table[cdk-table][recycleRows]', providers: [{ provide: _VIEW_REPEATER_STRATEGY, useClass: _RecycleViewRepeaterStrategy }] }] }] }); class DataRowOutlet { viewContainer = inject(ViewContainerRef); elementRef = inject(ElementRef); constructor() { const table = inject(CDK_TABLE); table._rowOutlet = this; table._outletAssigned(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: DataRowOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: DataRowOutlet, isStandalone: true, selector: "[rowOutlet]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: DataRowOutlet, decorators: [{ type: Directive, args: [{ selector: '[rowOutlet]' }] }], ctorParameters: () => [] }); class HeaderRowOutlet { viewContainer = inject(ViewContainerRef); elementRef = inject(ElementRef); constructor() { const table = inject(CDK_TABLE); table._headerRowOutlet = this; table._outletAssigned(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: HeaderRowOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: HeaderRowOutlet, isStandalone: true, selector: "[headerRowOutlet]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: HeaderRowOutlet, decorators: [{ type: Directive, args: [{ selector: '[headerRowOutlet]' }] }], ctorParameters: () => [] }); class FooterRowOutlet { viewContainer = inject(ViewContainerRef); elementRef = inject(ElementRef); constructor() { const table = inject(CDK_TABLE); table._footerRowOutlet = this; table._outletAssigned(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: FooterRowOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: FooterRowOutlet, isStandalone: true, selector: "[footerRowOutlet]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: FooterRowOutlet, decorators: [{ type: Directive, args: [{ selector: '[footerRowOutlet]' }] }], ctorParameters: () => [] }); class NoDataRowOutlet { viewContainer = inject(ViewContainerRef); elementRef = inject(ElementRef); constructor() { const table = inject(CDK_TABLE); table._noDataRowOutlet = this; table._outletAssigned(); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: NoDataRowOutlet, deps: [], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.0", type: NoDataRowOutlet, isStandalone: true, selector: "[noDataRowOutlet]", ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: NoDataRowOutlet, decorators: [{ type: Directive, args: [{ selector: '[noDataRowOutlet]' }] }], ctorParameters: () => [] }); class CdkTable { _differs = inject(IterableDiffers); _changeDetectorRef = inject(ChangeDetectorRef); _elementRef = inject(ElementRef); _dir = inject(Directionality, { optional: true }); _platform = inject(Platform); _viewRepeater = inject(_VIEW_REPEATER_STRATEGY); _viewportRuler = inject(ViewportRuler); _stickyPositioningListener = inject(STICKY_POSITIONING_LISTENER, { optional: true, skipSelf: true }); _document = inject(DOCUMENT); _data; _onDestroy = new Subject(); _renderRows; _renderChangeSubscription; _columnDefsByName = new Map(); _rowDefs; _headerRowDefs; _footerRowDefs; _dataDiffer; _defaultRowDef; _customColumnDefs = new Set(); _customRowDefs = new Set(); _customHeaderRowDefs = new Set(); _customFooterRowDefs = new Set(); _customNoDataRow; _headerRowDefChanged = true; _footerRowDefChanged = true; _stickyColumnStylesNeedReset = true; _forceRecalculateCellWidths = true; _cachedRenderRowsMap = new Map(); _isNativeHtmlTable; _stickyStyler; stickyCssClass = 'cdk-table-sticky'; needsPositionStickyOnElement = true; _isServer; _isShowingNoDataRow = false; _hasAllOutlets = false; _hasInitialized = false; _getCellRole() { if (this._cellRoleInternal === undefined) { const tableRole = this._elementRef.nativeElement.getAttribute('role'); return tableRole === 'grid' || tableRole === 'treegrid' ? 'gridcell' : 'cell'; } return this._cellRoleInternal; } _cellRoleInternal = undefined; get trackBy() { return this._trackByFn; } set trackBy(fn) { if ((typeof ngDevMode === 'undefined' || ngDevMode) && fn != null && typeof fn !== 'function') { console.warn(`trackBy must be a function, but received ${JSON.stringify(fn)}.`); } this._trackByFn = fn; } _trackByFn; get dataSource() { return this._dataSource; } set dataSource(dataSource) { if (this._dataSource !== dataSource) { this._switchDataSource(dataSource); } } _dataSource; get multiTemplateDataRows() { return this._multiTemplateDataRows; } set multiTemplateDataRows(value) { this._multiTemplateDataRows = value; if (this._rowOutlet && this._rowOutlet.viewContainer.length) { this._forceRenderDataRows(); this.updateStickyColumnStyles(); } } _multiTemplateDataRows = false; get fixedLayout() { return this._fixedLayout; } set fixedLayout(value) { this._fixedLayout = value; this._forceRecalculateCellWidths = true; this._stickyColumnStylesNeedReset = true; } _fixedLayout = false; contentChanged = new EventEmitter(); viewChange = new BehaviorSubject({ start: 0, end: Number.MAX_VALUE }); _rowOutlet; _headerRowOutlet; _footerRowOutlet; _noDataRowOutlet; _contentColumnDefs; _contentRowDefs; _contentHeaderRowDefs; _contentFooterRowDefs; _noDataRow; _injector = inject(Injector); constructor() { const role = inject(new HostAttributeToken('role'), { optional: true }); if (!role) { this._elementRef.nativeElement.setAttribute('role', 'table'); } this._isServer = !this._platform.isBrowser; this._isNativeHtmlTable = this._elementRef.nativeElement.nodeName === 'TABLE'; this._dataDiffer = this._differs.find([]).create((_i, dataRow) => { return this.trackBy ? this.trackBy(dataRow.dataIndex, dataRow.data) : dataRow; }); } ngOnInit() { this._setupStickyStyler(); this._viewportRuler.change().pipe(takeUntil(this._onDestroy)).subscribe(() => { this._forceRecalculateCellWidths = true; }); } ngAfterContentInit() { this._hasInitialized = true; } ngAfterContentChecked() { if (this._canRender()) { this._render(); } } ngOnDestroy() { this._stickyStyler?.destroy(); [this._rowOutlet?.viewContainer, this._headerRowOutlet?.viewContainer, this._footerRowOutlet?.viewContainer, this._cachedRenderRowsMap, this._customColumnDefs, this._customRowDefs, this._customHeaderRowDefs, this._customFooterRowDefs, this._columnDefsByName].forEach(def => { def?.clear(); }); this._headerRowDefs = []; this._footerRowDefs = []; this._defaultRowDef = null; this._onDestroy.next(); this._onDestroy.complete(); if (isDataSource(this.dataSource)) { this.dataSource.disconnect(this); } } renderRows() { this._renderRows = this._getAllRenderRows(); const changes = this._dataDiffer.diff(this._renderRows); if (!changes) { this._updateNoDataRow(); this.contentChanged.next(); return; } const viewContainer = this._rowOutlet.viewContainer; this._viewRepeater.applyChanges(changes, viewContainer, (record, _adjustedPreviousIndex, currentIndex) => this._getEmbeddedViewArgs(record.item, currentIndex), record => record.item.data, change => { if (change.operation === _ViewRepeaterOperation.INSERTED && change.context) { this._renderCellTemplateForItem(change.record.item.rowDef, change.context); } }); this._updateRowIndexContext(); changes.forEachIdentityChange(record => { const rowView = viewContainer.get(record.currentIndex); rowView.context.$implicit = record.item.data; }); this._updateNoDataRow(); this.contentChanged.next(); this.updateStickyColumnStyles(); } addColumnDef(columnDef) { this._customColumnDefs.add(columnDef); } removeColumnDef(columnDef) { this._customColumnDefs.delete(columnDef); } addRowDef(rowDef) { this._customRowDefs.add(rowDef); } removeRowDef(rowDef) { this._customRowDefs.delete(rowDef); } addHeaderRowDef(headerRowDef) { this._customHeaderRowDefs.add(headerRowDef); this._headerRowDefChanged = true; } removeHeaderRowDef(headerRowDef) { this._customHeaderRowDefs.delete(headerRowDef); this._headerRowDefChanged = true; } addFooterRowDef(footerRowDef) { this._customFooterRowDefs.add(footerRowDef); this._footerRowDefChanged = true; } removeFooterRowDef(footerRowDef) { this._customFooterRowDefs.delete(footerRowDef); this._footerRowDefChanged = true; } setNoDataRow(noDataRow) { this._customNoDataRow = noDataRow; } updateStickyHeaderRowStyles() { const headerRows = this._getRenderedRows(this._headerRowOutlet); if (this._isNativeHtmlTable) { const thead = closestTableSection(this._headerRowOutlet, 'thead'); if (thead) { thead.style.display = headerRows.length ? '' : 'none'; } } const stickyStates = this._headerRowDefs.map(def => def.sticky); this._stickyStyler.clearStickyPositioning(headerRows, ['top']); this._stickyStyler.stickRows(headerRows, stickyStates, 'top'); this._headerRowDefs.forEach(def => def.resetStickyChanged()); } updateStickyFooterRowStyles() { const footerRows = this._getRenderedRows(this._footerRowOutlet); if (this._isNativeHtmlTable) { const tfoot = closestTableSection(this._footerRowOutlet, 'tfoot'); if (tfoot) { tfoot.style.display = footerRows.length ? '' : 'none'; } } const stickyStates = this._footerRowDefs.map(def => def.sticky); this._stickyStyler.clearStickyPositioning(footerRows, ['bottom']); this._stickyStyler.stickRows(footerRows, stickyStates, 'bottom'); this._stickyStyler.updateStickyFooterContainer(this._elementRef.nativeElement, stickyStates); this._footerRowDefs.forEach(def => def.resetStickyChanged()); } updateStickyColumnStyles() { const headerRows = this._getRenderedRows(this._headerRowOutlet); const dataRows = this._getRenderedRows(this._rowOutlet); const footerRows = this._getRenderedRows(this._footerRowOutlet); if (this._isNativeHtmlTable && !this._fixedLayout || this._stickyColumnStylesNeedReset) { this._stickyStyler.clearStickyPositioning([...headerRows, ...dataRows, ...footerRows], ['left', 'right']); this._stickyColumnStylesNeedReset = false; } headerRows.forEach((headerRow, i) => { this._addStickyColumnStyles([headerRow], this._headerRowDefs[i]); }); this._rowDefs.forEach(rowDef => { const rows = []; for (let i = 0; i < dataRows.length; i++) { if (this._renderRows[i].rowDef === rowDef) { rows.push(dataRows[i]); } } this._addStickyColumnStyles(rows, rowDef); }); footerRows.forEach((footerRow, i) => { this._addStickyColumnStyles([footerRow], this._footerRowDefs[i]); }); Array.from(this._columnDefsByName.values()).forEach(def => def.resetStickyChanged()); } _outletAssigned() { if (!this._hasAllOutlets && this._rowOutlet && this._headerRowOutlet && this._footerRowOutlet && this._noDataRowOutlet) { this._hasAllOutlets = true; if (this._canRender()) { this._render(); } } } _canRender() { return this._hasAllOutlets && this._hasInitialized; } _render() { this._cacheRowDefs(); this._cacheColumnDefs(); if (!this._headerRowDefs.length && !this._footerRowDefs.length && !this._rowDefs.length && (typeof ngDevMode === 'undefined' || ngDevMode)) { throw getTableMissingRowDefsError(); } const columnsChanged = this._renderUpdatedColumns(); const rowDefsChanged = columnsChanged || this._headerRowDefChanged || this._footerRowDefChanged; this._stickyColumnStylesNeedReset = this._stickyColumnStylesNeedReset || rowDefsChanged; this._forceRecalculateCellWidths = rowDefsChanged; if (this._headerRowDefChanged) { this._forceRenderHeaderRows(); this._headerRowDefChanged = false; } if (this._footerRowDefChanged) { this._forceRenderFooterRows(); this._footerRowDefChanged = false; } if (this.dataSource && this._rowDefs.length > 0 && !this._renderChangeSubscription) { this._observeRenderChanges(); } else if (this._stickyColumnStylesNeedReset) { this.updateStickyColumnStyles(); } this._checkStickyStates(); } _getAllRenderRows() { const renderRows = []; const prevCachedRenderRows = this._cachedRenderRowsMap; this._cachedRenderRowsMap = new Map(); if (!this._data) { return renderRows; } for (let i = 0; i < this._data.length; i++) { let data = this._data[i]; const renderRowsForData = this._getRenderRowsForData(data, i, prevCachedRenderRows.get(data)); if (!this._cachedRenderRowsMap.has(data)) { this._cachedRenderRowsMap.set(data, new WeakMap()); } for (let j = 0; j < renderRowsForData.length; j++) { let renderRow = renderRowsForData[j]; const cache = this._cachedRenderRowsMap.get(renderRow.data); if (cache.has(renderRow.rowDef)) { cache.get(renderRow.rowDef).push(renderRow); } else { cache.set(renderRow.rowDef, [renderRow]); } renderRows.push(renderRow); } } return renderRows; } _getRenderRowsForData(data, dataIndex, cache) { const rowDefs = this._getRowDefs(dat