@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
98 lines • 14.3 kB
JavaScript
import { Directive, ElementRef, EventEmitter, HostBinding, inject, Input, Output, Renderer2 } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ResizeService } from '../resize/index';
import * as i0 from "@angular/core";
export class FixedHeaderTableDirective {
constructor() {
this._elementRef = inject(ElementRef);
this._renderer = inject(Renderer2);
this._resizeService = inject(ResizeService);
/** Emit when the table tries to load more data */
this.tablePaging = new EventEmitter();
/** Apply a class whenever the table has scrolled */
this._hasScrolled = false;
/** Unsubscribe from all observables on destroy */
this._onDestroy = new Subject();
}
/** Allow dataset changes to trigger re-layout */
set dataset(_dataset) {
requestAnimationFrame(() => this.setLayout());
}
ngOnInit() {
// add class to the table
this._renderer.addClass(this._elementRef.nativeElement, 'ux-fixed-header-table');
// locate the important elements
this._tableHead = this._elementRef.nativeElement.querySelector('thead');
this._tableBody = this._elementRef.nativeElement.querySelector('tbody');
// bind to scroll events on the table body
this._renderer.listen(this._tableBody, 'scroll', this.onScroll.bind(this));
// resize the table header to account for scrollbar
this.setLayout();
// if a resize occurs perform a relayout (this can be useful when displaying tables in modals)
this._resizeService.addResizeListener(this._elementRef.nativeElement).pipe(takeUntil(this._onDestroy))
.subscribe(() => this.setLayout());
// trigger the loading of the first page
this.tablePaging.emit();
}
ngOnDestroy() {
this._onDestroy.next();
this._onDestroy.complete();
}
/**
* Get the table element
* Primarily used by column width directive
*/
getTable() {
return this._elementRef.nativeElement;
}
/**
* Update the size of the table header to account for the scrollbar.
* This is important to keep the columns aligned
*/
setLayout() {
if (!this._tableBody || !this._tableHead) {
return;
}
// calculate the size of the scrollbar
const scrollbar = this._tableBody.offsetWidth - this._tableBody.clientWidth;
// add padding to the header to account for this
this._renderer.setStyle(this._tableHead, 'padding-right', scrollbar + 'px');
// set the desired height of the table body
this._renderer.setStyle(this._tableBody, 'height', typeof this.tableHeight === 'number' ? `${this.tableHeight}px` : this.tableHeight);
}
/**
* Handle scroll events
*/
onScroll() {
// determine if we are scrolled to the bottom and if so load the next page
const scrollTop = this._tableBody.scrollTop;
const scrollHeight = this._tableBody.scrollHeight - this._tableBody.offsetHeight;
const delta = Math.max(scrollTop, scrollHeight) - Math.min(scrollTop, scrollHeight);
// its possible for the difference to be a value < 1 when we are at the bottom. Account for this:
if (delta < 1) {
this.tablePaging.emit();
}
// update the class based on the scroll position
this._hasScrolled = (scrollTop > 0);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FixedHeaderTableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.12", type: FixedHeaderTableDirective, selector: "[uxFixedHeaderTable]", inputs: { dataset: "dataset", tableHeight: "tableHeight" }, outputs: { tablePaging: "tablePaging" }, host: { properties: { "class.ux-fixed-header-table-scrolled": "this._hasScrolled" } }, exportAs: ["ux-fixed-header-table"], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FixedHeaderTableDirective, decorators: [{
type: Directive,
args: [{
selector: '[uxFixedHeaderTable]',
exportAs: 'ux-fixed-header-table'
}]
}], propDecorators: { dataset: [{
type: Input
}], tableHeight: [{
type: Input
}], tablePaging: [{
type: Output
}], _hasScrolled: [{
type: HostBinding,
args: ['class.ux-fixed-header-table-scrolled']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4ZWQtaGVhZGVyLXRhYmxlLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9kaXJlY3RpdmVzL2ZpeGVkLWhlYWRlci10YWJsZS9maXhlZC1oZWFkZXItdGFibGUuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0SSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBTWhELE1BQU0sT0FBTyx5QkFBeUI7SUFKdEM7UUFLcUIsZ0JBQVcsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFakMsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUU5QixtQkFBYyxHQUFHLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQVV4RCxrREFBa0Q7UUFDeEMsZ0JBQVcsR0FBeUIsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUd6RSxvREFBb0Q7UUFDQyxpQkFBWSxHQUFZLEtBQUssQ0FBQztRQVFuRixrREFBa0Q7UUFDakMsZUFBVSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7S0E2RXJEO0lBbkdHLGlEQUFpRDtJQUNqRCxJQUFhLE9BQU8sQ0FBQyxRQUEwQjtRQUMzQyxxQkFBcUIsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBcUJELFFBQVE7UUFFSix5QkFBeUI7UUFDekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMs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eUI7bUdBQXpCLHlCQUF5Qjs7NEZBQXpCLHlCQUF5QjtrQkFKckMsU0FBUzttQkFBQztvQkFDUCxRQUFRLEVBQUUsc0JBQXNCO29CQUNoQyxRQUFRLEVBQUUsdUJBQXVCO2lCQUNwQzs4QkFTZ0IsT0FBTztzQkFBbkIsS0FBSztnQkFLRyxXQUFXO3NCQUFuQixLQUFLO2dCQUdJLFdBQVc7c0JBQXBCLE1BQU07Z0JBSThDLFlBQVk7c0JBQWhFLFdBQVc7dUJBQUMsc0NBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RCaW5kaW5nLCBpbmplY3QsIElucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0LCBSZW5kZXJlcjIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFJlc2l6ZVNlcnZpY2UgfSBmcm9tICcuLi9yZXNpemUvaW5kZXgnO1xuXG5ARGlyZWN0aXZlKHtcbiAgICBzZWxlY3RvcjogJ1t1eEZpeGVkSGVhZGVyVGFibGVdJyxcbiAgICBleHBvcnRBczogJ3V4LWZpeGVkLWhlYWRlci10YWJsZSdcbn0pXG5leHBvcnQgY2xhc3MgRml4ZWRIZWFkZXJUYWJsZURpcmVjdGl2ZTxUPiBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWYpO1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBfcmVuZGVyZXIgPSBpbmplY3QoUmVuZGVyZXIyKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3Jlc2l6ZVNlcnZpY2UgPSBpbmplY3QoUmVzaXplU2VydmljZSk7XG5cbiAgICAvKiogQWxsb3cgZGF0YXNldCBjaGFuZ2VzIHRvIHRyaWdnZXIgcmUtbGF5b3V0ICovXG4gICAgQElucHV0KCkgc2V0IGRhdGFzZXQoX2RhdGFzZXQ6IFJlYWRvbmx5QXJyYXk8VD4pIHtcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHRoaXMuc2V0TGF5b3V0KCkpO1xuICAgIH1cblxuICAgIC8qKiBEZWZpbmUgdGhlIHRhYmxlIGhlaWdodCAqL1xuICAgIEBJbnB1dCgpIHRhYmxlSGVpZ2h0OiBudW1iZXIgfCBzdHJpbmc7XG5cbiAgICAvKiogRW1pdCB3aGVuIHRoZSB0YWJsZSB0cmllcyB0byBsb2FkIG1vcmUgZGF0YSAqL1xuICAgIEBPdXRwdXQoKSB0YWJsZVBhZ2luZzogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcblxuXG4gICAgLyoqIEFwcGx5IGEgY2xhc3Mgd2hlbmV2ZXIgdGhlIHRhYmxlIGhhcyBzY3JvbGxlZCAqL1xuICAgIEBIb3N0QmluZGluZygnY2xhc3MudXgtZml4ZWQtaGVhZGVyLXRhYmxlLXNjcm9sbGVkJykgX2hhc1Njcm9sbGVkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogU3RvcmUgdGhlIHRhYmxlIGhlYWQgZWxlbWVudCAqL1xuICAgIHByaXZhdGUgX3RhYmxlSGVhZDogSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ7XG5cbiAgICAvKiogU3RvcmUgdGhlIHRhYmxlIGJvZHkgZWxlbWVudCAqL1xuICAgIHByaXZhdGUgX3RhYmxlQm9keTogSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ7XG5cbiAgICAvKiogVW5zdWJzY3JpYmUgZnJvbSBhbGwgb2JzZXJ2YWJsZXMgb24gZGVzdHJveSAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgX29uRGVzdHJveSA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcblxuICAgICAgICAvLyBhZGQgY2xhc3MgdG8gdGhlIHRhYmxlXG4gICAgICAgIHRoaXMuX3JlbmRlcmVyLmFkZENsYXNzKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ3V4LWZpeGVkLWhlYWRlci10YWJsZScpO1xuXG4gICAgICAgIC8vIGxvY2F0ZSB0aGUgaW1wb3J0YW50IGVsZW1lbnRzXG4gICAgICAgIHRoaXMuX3RhYmxlSGVhZCA9IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCd0aGVhZCcpIGFzIEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50O1xuICAgICAgICB0aGlzLl90YWJsZUJvZHkgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcigndGJvZHknKSBhcyBIVE1MVGFibGVTZWN0aW9uRWxlbWVudDtcblxuICAgICAgICAvLyBiaW5kIHRvIHNjcm9sbCBldmVudHMgb24gdGhlIHRhYmxlIGJvZHlcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIubGlzdGVuKHRoaXMuX3RhYmxlQm9keSwgJ3Njcm9sbCcsIHRoaXMub25TY3JvbGwuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgLy8gcmVzaXplIHRoZSB0YWJsZSBoZWFkZXIgdG8gYWNjb3VudCBmb3Igc2Nyb2xsYmFyXG4gICAgICAgIHRoaXMuc2V0TGF5b3V0KCk7XG5cbiAgICAgICAgLy8gaWYgYSByZXNpemUgb2NjdXJzIHBlcmZvcm0gYSByZWxheW91dCAodGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gZGlzcGxheWluZyB0YWJsZXMgaW4gbW9kYWxzKVxuICAgICAgICB0aGlzLl9yZXNpemVTZXJ2aWNlLmFkZFJlc2l6ZUxpc3RlbmVyKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkucGlwZSh0YWtlVW50aWwodGhpcy5fb25EZXN0cm95KSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5zZXRMYXlvdXQoKSk7XG5cbiAgICAgICAgLy8gdHJpZ2dlciB0aGUgbG9hZGluZyBvZiB0aGUgZmlyc3QgcGFnZVxuICAgICAgICB0aGlzLnRhYmxlUGFnaW5nLmVtaXQoKTtcbiAgICB9XG5cbiAgICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95Lm5leHQoKTtcbiAgICAgICAgdGhpcy5fb25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSB0YWJsZSBlbGVtZW50XG4gICAgICogUHJpbWFyaWx5IHVzZWQgYnkgY29sdW1uIHdpZHRoIGRpcmVjdGl2ZVxuICAgICAqL1xuICAgIGdldFRhYmxlKCk6IEhUTUxUYWJsZUVsZW1lbnQge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2l6ZSBvZiB0aGUgdGFibGUgaGVhZGVyIHRvIGFjY291bnQgZm9yIHRoZSBzY3JvbGxiYXIuXG4gICAgICogVGhpcyBpcyBpbXBvcnRhbnQgdG8ga2VlcCB0aGUgY29sdW1ucyBhbGlnbmVkXG4gICAgICovXG4gICAgc2V0TGF5b3V0KCk6IHZvaWQge1xuXG4gICAgICAgIGlmICghdGhpcy5fdGFibGVCb2R5IHx8ICF0aGlzLl90YWJsZUhlYWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgc2l6ZSBvZiB0aGUgc2Nyb2xsYmFyXG4gICAgICAgIGNvbnN0IHNjcm9sbGJhciA9IHRoaXMuX3RhYmxlQm9keS5vZmZzZXRXaWR0aCAtIHRoaXMuX3RhYmxlQm9keS5jbGllbnRXaWR0aDtcblxuICAgICAgICAvLyBhZGQgcGFkZGluZyB0byB0aGUgaGVhZGVyIHRvIGFjY291bnQgZm9yIHRoaXNcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUodGhpcy5fdGFibGVIZWFkLCAncGFkZGluZy1yaWdodCcsIHNjcm9sbGJhciArICdweCcpO1xuXG4gICAgICAgIC8vIHNldCB0aGUgZGVzaXJlZCBoZWlnaHQgb2YgdGhlIHRhYmxlIGJvZHlcbiAgICAgICAgdGhpcy5fcmVuZGVyZXIuc2V0U3R5bGUodGhpcy5fdGFibGVCb2R5LCAnaGVpZ2h0JywgdHlwZW9mIHRoaXMudGFibGVIZWlnaHQgPT09ICdudW1iZXInID8gYCR7dGhpcy50YWJsZUhlaWdodH1weGAgOiB0aGlzLnRhYmxlSGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgc2Nyb2xsIGV2ZW50c1xuICAgICAqL1xuICAgIHByaXZhdGUgb25TY3JvbGwoKTogdm9pZCB7XG5cbiAgICAgICAgLy8gZGV0ZXJtaW5lIGlmIHdlIGFyZSBzY3JvbGxlZCB0byB0aGUgYm90dG9tIGFuZCBpZiBzbyBsb2FkIHRoZSBuZXh0IHBhZ2VcbiAgICAgICAgY29uc3Qgc2Nyb2xsVG9wID0gdGhpcy5fdGFibGVCb2R5LnNjcm9sbFRvcDtcbiAgICAgICAgY29uc3Qgc2Nyb2xsSGVpZ2h0ID0gdGhpcy5fdGFibGVCb2R5LnNjcm9sbEhlaWdodCAtIHRoaXMuX3RhYmxlQm9keS5vZmZzZXRIZWlnaHQ7XG4gICAgICAgIGNvbnN0IGRlbHRhID0gTWF0aC5tYXgoc2Nyb2xsVG9wLCBzY3JvbGxIZWlnaHQpIC0gTWF0aC5taW4oc2Nyb2xsVG9wLCBzY3JvbGxIZWlnaHQpO1xuXG4gICAgICAgIC8vIGl0cyBwb3NzaWJsZSBmb3IgdGhlIGRpZmZlcmVuY2UgdG8gYmUgYSB2YWx1ZSA8IDEgd2hlbiB3ZSBhcmUgYXQgdGhlIGJvdHRvbS4gQWNjb3VudCBmb3IgdGhpczpcbiAgICAgICAgaWYgKGRlbHRhIDwgMSkge1xuICAgICAgICAgICAgdGhpcy50YWJsZVBhZ2luZy5lbWl0KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB1cGRhdGUgdGhlIGNsYXNzIGJhc2VkIG9uIHRoZSBzY3JvbGwgcG9zaXRpb25cbiAgICAgICAgdGhpcy5faGFzU2Nyb2xsZWQgPSAoc2Nyb2xsVG9wID4gMCk7XG4gICAgfVxuXG59XG4iXX0=