UNPKG

ng-cdk-table-virtual-scroll

Version:
354 lines (346 loc) 15.1 kB
import { __extends, __decorate } from 'tslib'; import { Injectable, NgZone, Input, ContentChild, Directive, forwardRef, NgModule } from '@angular/core'; import { distinctUntilChanged, filter, tap, takeWhile, takeUntil, switchMap, map } from 'rxjs/operators'; import { BehaviorSubject, Subscription, ReplaySubject, Subject } from 'rxjs'; import { VIRTUAL_SCROLL_STRATEGY } from '@angular/cdk/scrolling'; import { DataSource, CdkTable } from '@angular/cdk/table'; var TableVirtualScrollDataSource = /** @class */ (function (_super) { __extends(TableVirtualScrollDataSource, _super); function TableVirtualScrollDataSource(initialData) { if (initialData === void 0) { initialData = []; } var _this = _super.call(this) || this; /** Stream emitting render data to the table (depends on ordered data changes). */ _this._renderData = new BehaviorSubject([]); /** * Subscription to the changes that should trigger an update to the table's rendered rows, such * as filtering, sorting, pagination, or base data changes. */ _this._renderChangesSubscription = null; _this._data = new BehaviorSubject(initialData); _this.updateChangeSubscription(); return _this; } Object.defineProperty(TableVirtualScrollDataSource.prototype, "data", { /** Array of data that should be rendered by the table, where each object represents one row. */ get: function () { return this._data.value; }, set: function (data) { this._data.next(data); }, enumerable: true, configurable: true }); TableVirtualScrollDataSource.prototype.updateChangeSubscription = function () { var _this = this; this.initStreams(); this._renderChangesSubscription = new Subscription(); this._renderChangesSubscription.add(this._data.subscribe(function (data) { return _this.dataToRender$.next(data); })); this._renderChangesSubscription.add(this.dataOfRange$.subscribe(function (data) { return _this._renderData.next(data); })); }; TableVirtualScrollDataSource.prototype.initStreams = function () { if (!this.streamsReady) { this.dataToRender$ = new ReplaySubject(1); this.dataOfRange$ = new ReplaySubject(1); this.streamsReady = true; } }; /** * Used by the MatTable. Called when it connects to the data source. * @private */ TableVirtualScrollDataSource.prototype.connect = function () { if (!this._renderChangesSubscription) { this.updateChangeSubscription(); } return this._renderData; }; /** * Used by the MatTable. Called when it disconnects from the data source. * @private */ TableVirtualScrollDataSource.prototype.disconnect = function () { if (this._renderChangesSubscription) { this._renderChangesSubscription.unsubscribe(); } this._renderChangesSubscription = null; }; return TableVirtualScrollDataSource; }(DataSource)); var FixedSizeTableVirtualScrollStrategy = /** @class */ (function () { function FixedSizeTableVirtualScrollStrategy() { this.indexChange = new Subject(); this.stickyChange = new Subject(); this.renderedRangeStream = new BehaviorSubject({ start: 0, end: 0 }); this.scrolledIndexChange = this.indexChange.pipe(distinctUntilChanged()); this._dataLength = 0; } Object.defineProperty(FixedSizeTableVirtualScrollStrategy.prototype, "dataLength", { get: function () { return this._dataLength; }, set: function (value) { this._dataLength = value; this.onDataLengthChanged(); }, enumerable: true, configurable: true }); FixedSizeTableVirtualScrollStrategy.prototype.attach = function (viewport) { this.viewport = viewport; this.viewport.renderedRangeStream.subscribe(this.renderedRangeStream); this.onDataLengthChanged(); }; FixedSizeTableVirtualScrollStrategy.prototype.detach = function () { this.indexChange.complete(); this.stickyChange.complete(); this.renderedRangeStream.complete(); }; FixedSizeTableVirtualScrollStrategy.prototype.onContentScrolled = function () { this.updateContent(); }; FixedSizeTableVirtualScrollStrategy.prototype.onDataLengthChanged = function () { if (this.viewport) { this.viewport.setTotalContentSize(this.dataLength * this.rowHeight + this.headerHeight + this.footerHeight); } this.updateContent(); }; FixedSizeTableVirtualScrollStrategy.prototype.onContentRendered = function () { // no-op }; FixedSizeTableVirtualScrollStrategy.prototype.onRenderedOffsetChanged = function () { // no-op }; FixedSizeTableVirtualScrollStrategy.prototype.scrollToIndex = function (index, behavior) { if (!this.viewport || !this.rowHeight) { return; } this.viewport.scrollToOffset((index - 1) * this.rowHeight + this.headerHeight); }; FixedSizeTableVirtualScrollStrategy.prototype.setConfig = function (configs) { var rowHeight = configs.rowHeight, headerHeight = configs.headerHeight, footerHeight = configs.footerHeight, bufferMultiplier = configs.bufferMultiplier; if (this.rowHeight === rowHeight && this.headerHeight === headerHeight && this.footerHeight === footerHeight && this.bufferMultiplier === bufferMultiplier) { return; } this.rowHeight = rowHeight; this.headerHeight = headerHeight; this.footerHeight = footerHeight; this.bufferMultiplier = bufferMultiplier; this.onDataLengthChanged(); }; FixedSizeTableVirtualScrollStrategy.prototype.updateContent = function () { if (!this.viewport || !this.rowHeight) { return; } var scrollOffset = this.viewport.measureScrollOffset(); var amount = Math.ceil(this.viewport.getViewportSize() / this.rowHeight); var offset = Math.max(scrollOffset - this.headerHeight, 0); var buffer = Math.ceil(amount * this.bufferMultiplier); var skip = Math.round(offset / this.rowHeight); var index = Math.max(0, skip); var start = Math.max(0, index - buffer); var end = Math.min(this.dataLength, index + amount + buffer); var renderedOffset = start * this.rowHeight; this.viewport.setRenderedContentOffset(renderedOffset); this.viewport.setRenderedRange({ start: start, end: end }); this.indexChange.next(index); this.stickyChange.next(renderedOffset); }; FixedSizeTableVirtualScrollStrategy = __decorate([ Injectable() ], FixedSizeTableVirtualScrollStrategy); return FixedSizeTableVirtualScrollStrategy; }()); function _tableVirtualScrollDirectiveStrategyFactory(tableDir) { return tableDir.scrollStrategy; } var stickyHeaderSelector = '.cdk-header-row .cdk-table-sticky'; var stickyFooterSelector = '.cdk-footer-row .cdk-table-sticky'; var defaults = { rowHeight: 48, headerHeight: 56, headerEnabled: true, footerHeight: 48, footerEnabled: false, bufferMultiplier: 0.7, }; var TableItemSizeDirective = /** @class */ (function () { function TableItemSizeDirective(zone) { this.zone = zone; this.alive = true; // tslint:disable-next-line:no-input-rename this.rowHeight = defaults.rowHeight; this.headerEnabled = defaults.headerEnabled; this.headerHeight = defaults.headerHeight; this.footerEnabled = defaults.footerEnabled; this.footerHeight = defaults.footerHeight; this.bufferMultiplier = defaults.bufferMultiplier; this.scrollStrategy = new FixedSizeTableVirtualScrollStrategy(); this.dataSourceChanges = new Subject(); } TableItemSizeDirective_1 = TableItemSizeDirective; TableItemSizeDirective.prototype.ngOnDestroy = function () { this.alive = false; this.dataSourceChanges.complete(); }; TableItemSizeDirective.prototype.isAlive = function () { var _this = this; return function () { return _this.alive; }; }; TableItemSizeDirective.prototype.isStickyEnabled = function () { return (!!this.scrollStrategy.viewport && this.table['_headerRowDefs'] .map(function (def) { return def.sticky; }) .reduce(function (prevState, state) { return prevState && state; }, true)); }; TableItemSizeDirective.prototype.ngAfterContentInit = function () { var _this = this; var switchDataSourceOrigin = this.table['_switchDataSource']; this.table['_switchDataSource'] = function (dataSource) { switchDataSourceOrigin.call(_this.table, dataSource); _this.connectDataSource(dataSource); }; this.connectDataSource(this.table.dataSource); this.scrollStrategy.stickyChange .pipe(filter(function () { return _this.isStickyEnabled(); }), tap(function () { if (!_this.stickyPositions) { _this.initStickyPositions(); } }), takeWhile(this.isAlive())) .subscribe(function (stickyOffset) { _this.setSticky(stickyOffset); }); }; TableItemSizeDirective.prototype.connectDataSource = function (dataSource) { var _this = this; this.dataSourceChanges.next(); if (dataSource instanceof TableVirtualScrollDataSource) { dataSource.dataToRender$ .pipe(distinctUntilChanged(), takeUntil(this.dataSourceChanges), takeWhile(this.isAlive()), tap(function (data) { return (_this.scrollStrategy.dataLength = data.length); }), switchMap(function (data) { return _this.scrollStrategy.renderedRangeStream.pipe(map(function (_a) { var start = _a.start, end = _a.end; return typeof start !== 'number' || typeof end !== 'number' ? data : data.slice(start, end); })); })) .subscribe(function (data) { _this.zone.run(function () { dataSource.dataOfRange$.next(data); }); }); } else { throw new Error('[tvsItemSize] requires TableVirtualScrollDataSource be set as [dataSource] of [cdk-table]'); } }; TableItemSizeDirective.prototype.ngOnChanges = function () { var config = { rowHeight: +this.rowHeight || defaults.rowHeight, headerHeight: this.headerEnabled ? +this.headerHeight || defaults.headerHeight : 0, footerHeight: this.footerEnabled ? +this.footerHeight || defaults.footerHeight : 0, bufferMultiplier: +this.bufferMultiplier || defaults.bufferMultiplier, }; this.scrollStrategy.setConfig(config); }; TableItemSizeDirective.prototype.setSticky = function (offset) { var _this = this; this.scrollStrategy.viewport.elementRef.nativeElement .querySelectorAll(stickyHeaderSelector) .forEach(function (el) { var parent = el.parentElement; var baseOffset = 0; if (_this.stickyPositions.has(parent)) { baseOffset = _this.stickyPositions.get(parent); } el.style.top = baseOffset - offset + "px"; }); this.scrollStrategy.viewport.elementRef.nativeElement .querySelectorAll(stickyFooterSelector) .forEach(function (el) { var parent = el.parentElement; var baseOffset = 0; if (_this.stickyPositions.has(parent)) { baseOffset = _this.stickyPositions.get(parent); } el.style.bottom = -baseOffset + offset + "px"; }); }; TableItemSizeDirective.prototype.initStickyPositions = function () { var _this = this; this.stickyPositions = new Map(); this.scrollStrategy.viewport.elementRef.nativeElement .querySelectorAll(stickyHeaderSelector) .forEach(function (el) { var parent = el.parentElement; if (!_this.stickyPositions.has(parent)) { _this.stickyPositions.set(parent, parent.offsetTop); } }); }; var TableItemSizeDirective_1; TableItemSizeDirective.ctorParameters = function () { return [ { type: NgZone } ]; }; __decorate([ Input('tvsItemSize') ], TableItemSizeDirective.prototype, "rowHeight", void 0); __decorate([ Input() ], TableItemSizeDirective.prototype, "headerEnabled", void 0); __decorate([ Input() ], TableItemSizeDirective.prototype, "headerHeight", void 0); __decorate([ Input() ], TableItemSizeDirective.prototype, "footerEnabled", void 0); __decorate([ Input() ], TableItemSizeDirective.prototype, "footerHeight", void 0); __decorate([ Input() ], TableItemSizeDirective.prototype, "bufferMultiplier", void 0); __decorate([ ContentChild(CdkTable, { static: false }) ], TableItemSizeDirective.prototype, "table", void 0); TableItemSizeDirective = TableItemSizeDirective_1 = __decorate([ Directive({ selector: 'cdk-virtual-scroll-viewport[tvsItemSize]', providers: [ { provide: VIRTUAL_SCROLL_STRATEGY, useFactory: _tableVirtualScrollDirectiveStrategyFactory, deps: [forwardRef(function () { return TableItemSizeDirective_1; })], }, ], }) ], TableItemSizeDirective); return TableItemSizeDirective; }()); var TableVirtualScrollModule = /** @class */ (function () { function TableVirtualScrollModule() { } TableVirtualScrollModule = __decorate([ NgModule({ declarations: [TableItemSizeDirective], exports: [TableItemSizeDirective], imports: [], }) ], TableVirtualScrollModule); return TableVirtualScrollModule; }()); /* * Public API Surface of ng-fixed-size-table-virtual-scroll */ /** * Generated bundle index. Do not edit. */ export { FixedSizeTableVirtualScrollStrategy, TableItemSizeDirective, TableVirtualScrollDataSource, TableVirtualScrollModule, _tableVirtualScrollDirectiveStrategyFactory }; //# sourceMappingURL=ng-cdk-table-virtual-scroll.js.map