@jase7/ng-mat-select-infinite-scroll
Version:
Adds missing infinite scroll functionality for the angular material select component
85 lines • 11.6 kB
JavaScript
import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { debounceTime, takeUntil, tap } from 'rxjs/operators';
import { fromEvent, Subject } from 'rxjs';
import * as i0 from "@angular/core";
import * as i1 from "@angular/material/legacy-select";
/** The height of the select items in `em` units. */
const SELECT_ITEM_HEIGHT_EM = 3;
export class MatSelectInfiniteScrollDirective {
constructor(matSelect, ngZone) {
this.matSelect = matSelect;
this.ngZone = ngZone;
this.threshold = '15%';
this.debounceTime = 150;
this.infiniteScroll = new EventEmitter();
this.thrPx = 0;
this.thrPc = 0;
this.singleOptionHeight = SELECT_ITEM_HEIGHT_EM;
this.destroyed$ = new Subject();
}
ngOnInit() {
this.evaluateThreshold();
}
ngAfterViewInit() {
this.matSelect.openedChange.pipe(takeUntil(this.destroyed$)).subscribe((opened) => {
if (opened) {
this.panel = this.matSelect.panel.nativeElement;
this.singleOptionHeight = this.getSelectItemHeightPx();
this.registerScrollListener();
}
});
}
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
}
evaluateThreshold() {
if (this.threshold.lastIndexOf('%') > -1) {
this.thrPx = 0;
this.thrPc = (parseFloat(this.threshold) / 100);
}
else {
this.thrPx = parseFloat(this.threshold);
this.thrPc = 0;
}
}
registerScrollListener() {
fromEvent(this.panel, 'scroll').pipe(takeUntil(this.destroyed$), debounceTime(this.debounceTime), tap((event) => {
this.handleScrollEvent(event);
})).subscribe();
}
handleScrollEvent(event) {
this.ngZone.runOutsideAngular(() => {
if (this.complete) {
return;
}
const countOfRenderedOptions = this.matSelect.options.length;
const infiniteScrollDistance = this.singleOptionHeight * countOfRenderedOptions;
const threshold = this.thrPc !== 0 ? (infiniteScrollDistance * this.thrPc) : this.thrPx;
const scrolledDistance = this.panel.clientHeight + event.target.scrollTop;
if ((scrolledDistance + threshold) >= infiniteScrollDistance) {
this.ngZone.run(() => this.infiniteScroll.emit());
}
});
}
getSelectItemHeightPx() {
return parseFloat(getComputedStyle(this.panel).fontSize) * SELECT_ITEM_HEIGHT_EM;
}
}
MatSelectInfiniteScrollDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MatSelectInfiniteScrollDirective, deps: [{ token: i1.MatLegacySelect }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive });
MatSelectInfiniteScrollDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.9", type: MatSelectInfiniteScrollDirective, selector: "[msInfiniteScroll]", inputs: { threshold: "threshold", debounceTime: "debounceTime", complete: "complete" }, outputs: { infiniteScroll: "infiniteScroll" }, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MatSelectInfiniteScrollDirective, decorators: [{
type: Directive,
args: [{
selector: '[msInfiniteScroll]'
}]
}], ctorParameters: function () { return [{ type: i1.MatLegacySelect }, { type: i0.NgZone }]; }, propDecorators: { threshold: [{
type: Input
}], debounceTime: [{
type: Input
}], complete: [{
type: Input
}], infiniteScroll: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LXNlbGVjdC1pbmZpbml0ZS1zY3JvbGwuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctbWF0LXNlbGVjdC1pbmZpbml0ZS1zY3JvbGwvc3JjL2xpYi9tYXQtc2VsZWN0LWluZmluaXRlLXNjcm9sbC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFnQixTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBNkIsTUFBTSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBRS9HLE9BQU8sRUFBQyxZQUFZLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzVELE9BQU8sRUFBQyxTQUFTLEVBQUUsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDOzs7QUFFeEMsb0RBQW9EO0FBQ3BELE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0FBS2hDLE1BQU0sT0FBTyxnQ0FBZ0M7SUFjM0MsWUFBb0IsU0FBb0IsRUFBVSxNQUFjO1FBQTVDLGNBQVMsR0FBVCxTQUFTLENBQVc7UUFBVSxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBWnZELGNBQVMsR0FBRyxLQUFLLENBQUM7UUFDbEIsaUJBQVksR0FBRyxHQUFHLENBQUM7UUFFbEIsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRzVDLFVBQUssR0FBRyxDQUFDLENBQUM7UUFDVixVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsdUJBQWtCLEdBQUcscUJBQXFCLENBQUM7UUFFM0MsZUFBVSxHQUFHLElBQUksT0FBTyxFQUFXLENBQUM7SUFHNUMsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsZUFBZTtRQUNiLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDOUIsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFV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QUdVLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNJLGNBQWM7c0JBQXZCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0FmdGVyVmlld0luaXQsIERpcmVjdGl2ZSwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgTmdab25lLCBPbkRlc3Ryb3ksIE9uSW5pdCwgT3V0cHV0fSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHtNYXRMZWdhY3lTZWxlY3QgYXMgTWF0U2VsZWN0fSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9sZWdhY3ktc2VsZWN0JztcclxuaW1wb3J0IHtkZWJvdW5jZVRpbWUsIHRha2VVbnRpbCwgdGFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcbmltcG9ydCB7ZnJvbUV2ZW50LCBTdWJqZWN0fSBmcm9tICdyeGpzJztcclxuXHJcbi8qKiBUaGUgaGVpZ2h0IG9mIHRoZSBzZWxlY3QgaXRlbXMgaW4gYGVtYCB1bml0cy4gKi9cclxuY29uc3QgU0VMRUNUX0lURU1fSEVJR0hUX0VNID0gMztcclxuXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW21zSW5maW5pdGVTY3JvbGxdJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgTWF0U2VsZWN0SW5maW5pdGVTY3JvbGxEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdCB7XHJcblxyXG4gIEBJbnB1dCgpIHRocmVzaG9sZCA9ICcxNSUnO1xyXG4gIEBJbnB1dCgpIGRlYm91bmNlVGltZSA9IDE1MDtcclxuICBASW5wdXQoKSBjb21wbGV0ZSE6IGJvb2xlYW47XHJcbiAgQE91dHB1dCgpIGluZmluaXRlU2Nyb2xsID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICBwcml2YXRlIHBhbmVsITogRWxlbWVudDtcclxuICBwcml2YXRlIHRoclB4ID0gMDtcclxuICBwcml2YXRlIHRoclBjID0gMDtcclxuICBwcml2YXRlIHNpbmdsZU9wdGlvbkhlaWdodCA9IFNFTEVDVF9JVEVNX0hFSUdIVF9FTTtcclxuXHJcbiAgcHJpdmF0ZSBkZXN0cm95ZWQkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBtYXRTZWxlY3Q6IE1hdFNlbGVjdCwgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSkge1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICB0aGlzLmV2YWx1YXRlVGhyZXNob2xkKCk7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLm1hdFNlbGVjdC5vcGVuZWRDaGFuZ2UucGlwZShcclxuICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveWVkJClcclxuICAgICkuc3Vic2NyaWJlKChvcGVuZWQpID0+IHtcclxuICAgICAgaWYgKG9wZW5lZCkge1xyXG4gICAgICAgIHRoaXMucGFuZWwgPSB0aGlzLm1hdFNlbGVjdC5wYW5lbC5uYXRpdmVFbGVtZW50O1xyXG4gICAgICAgIHRoaXMuc2luZ2xlT3B0aW9uSGVpZ2h0ID0gdGhpcy5nZXRTZWxlY3RJdGVtSGVpZ2h0UHgoKTtcclxuICAgICAgICB0aGlzLnJlZ2lzdGVyU2Nyb2xsTGlzdGVuZXIoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpIHtcclxuICAgIHRoaXMuZGVzdHJveWVkJC5uZXh0KHRydWUpO1xyXG4gICAgdGhpcy5kZXN0cm95ZWQkLmNvbXBsZXRlKCk7XHJcbiAgfVxyXG5cclxuICBldmFsdWF0ZVRocmVzaG9sZCgpIHtcclxuICAgIGlmICh0aGlzLnRocmVzaG9sZC5sYXN0SW5kZXhPZignJScpID4gLTEpIHtcclxuICAgICAgdGhpcy50aHJQeCA9IDA7XHJcbiAgICAgIHRoaXMudGhyUGMgPSAocGFyc2VGbG9hdCh0aGlzLnRocmVzaG9sZCkgLyAxMDApO1xyXG5cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMudGhyUHggPSBwYXJzZUZsb2F0KHRoaXMudGhyZXNob2xkKTtcclxuICAgICAgdGhpcy50aHJQYyA9IDA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWdpc3RlclNjcm9sbExpc3RlbmVyKCkge1xyXG4gICAgZnJvbUV2ZW50KHRoaXMucGFuZWwsICdzY3JvbGwnKS5waXBlKFxyXG4gICAgICB0YWtlVW50aWwodGhpcy5kZXN0cm95ZWQkKSxcclxuICAgICAgZGVib3VuY2VUaW1lKHRoaXMuZGVib3VuY2VUaW1lKSxcclxuICAgICAgdGFwKChldmVudCkgPT4ge1xyXG4gICAgICAgIHRoaXMuaGFuZGxlU2Nyb2xsRXZlbnQoZXZlbnQpO1xyXG4gICAgICB9KVxyXG4gICAgKS5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIGhhbmRsZVNjcm9sbEV2ZW50KGV2ZW50OiBhbnkpIHtcclxuICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgaWYgKHRoaXMuY29tcGxldGUpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgY291bnRPZlJlbmRlcmVkT3B0aW9ucyA9IHRoaXMubWF0U2VsZWN0Lm9wdGlvbnMubGVuZ3RoO1xyXG4gICAgICBjb25zdCBpbmZpbml0ZVNjcm9sbERpc3RhbmNlID0gdGhpcy5zaW5nbGVPcHRpb25IZWlnaHQgKiBjb3VudE9mUmVuZGVyZWRPcHRpb25zO1xyXG4gICAgICBjb25zdCB0aHJlc2hvbGQgPSB0aGlzLnRoclBjICE9PSAwID8gKGluZmluaXRlU2Nyb2xsRGlzdGFuY2UgKiB0aGlzLnRoclBjKSA6IHRoaXMudGhyUHg7XHJcblxyXG4gICAgICBjb25zdCBzY3JvbGxlZERpc3RhbmNlID0gdGhpcy5wYW5lbC5jbGllbnRIZWlnaHQgKyBldmVudC50YXJnZXQuc2Nyb2xsVG9wO1xyXG5cclxuICAgICAgaWYgKChzY3JvbGxlZERpc3RhbmNlICsgdGhyZXNob2xkKSA+PSBpbmZpbml0ZVNjcm9sbERpc3RhbmNlKSB7XHJcbiAgICAgICAgdGhpcy5uZ1pvbmUucnVuKCgpID0+IHRoaXMuaW5maW5pdGVTY3JvbGwuZW1pdCgpKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBnZXRTZWxlY3RJdGVtSGVpZ2h0UHgoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBwYXJzZUZsb2F0KGdldENvbXB1dGVkU3R5bGUodGhpcy5wYW5lbCkuZm9udFNpemUpICogU0VMRUNUX0lURU1fSEVJR0hUX0VNO1xyXG4gIH1cclxuXHJcbn1cclxuIl19