ng-mat-select-infinite-scroll
Version:
Adds missing infinite scroll functionality for the angular material select component
148 lines (141 loc) • 7.24 kB
JavaScript
import * as i0 from '@angular/core';
import { Injectable, EventEmitter, Directive, Input, Output, NgModule } from '@angular/core';
import { takeUntil, debounceTime, tap, delay } from 'rxjs/operators';
import { Subject, fromEvent } from 'rxjs';
import * as i1 from '@angular/material/select';
import { MatSelectModule } from '@angular/material/select';
class InfiniteScrollService {
constructor(ngZone) {
this.ngZone = ngZone;
this.threshold = '15%';
this.debounceTime = 150;
this.thrPx = 0;
this.thrPc = 0;
this.destroyed$ = new Subject();
}
initialize(panel, selectItemHeightPx, config) {
this.threshold = config.threshold;
this.debounceTime = config.debounceTime;
this.complete = config.complete;
this.panel = panel;
this.selectItemHeightPx = selectItemHeightPx;
this.evaluateThreshold();
}
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(infiniteScrollCallback) {
fromEvent(this.panel, 'scroll').pipe(takeUntil(this.destroyed$), debounceTime(this.debounceTime), tap((event) => {
this.handleScrollEvent(event, infiniteScrollCallback);
})).subscribe();
}
handleScrollEvent(event, infiniteScrollCallback) {
this.ngZone.runOutsideAngular(() => {
if (this.complete) {
return;
}
const countOfRenderedOptions = Math.round(this.panel.scrollHeight / this.selectItemHeightPx);
const infiniteScrollDistance = this.selectItemHeightPx * 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(infiniteScrollCallback);
}
});
}
destroy() {
this.destroyed$.next();
this.destroyed$.complete();
}
}
InfiniteScrollService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InfiniteScrollService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
InfiniteScrollService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InfiniteScrollService, providedIn: 'root' });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InfiniteScrollService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return [{ type: i0.NgZone }]; } });
/** The height of the select items in `em` units. */
const SELECT_ITEM_HEIGHT_EM = 3;
class MatSelectInfiniteScrollDirective {
constructor(matSelect, infiniteScrollService) {
this.matSelect = matSelect;
this.infiniteScrollService = infiniteScrollService;
this.threshold = '15%';
this.debounceTime = 150;
this.infiniteScroll = new EventEmitter();
this.destroyed$ = new Subject();
}
ngAfterViewInit() {
this.matSelect.openedChange.pipe(
//Wait for the panel to be rendered (https://github.com/angular/components/issues/30596)
delay(0), takeUntil(this.destroyed$)).subscribe((opened) => {
if (opened) {
const panel = this.matSelect.panel.nativeElement;
const selectItemHeightPx = this.getSelectItemHeightPx(panel);
this.infiniteScrollService.initialize(panel, selectItemHeightPx, {
threshold: this.threshold,
debounceTime: this.debounceTime,
complete: this.complete
});
this.infiniteScrollService.registerScrollListener(() => this.infiniteScroll.emit());
}
});
}
getSelectItemHeightPx(panel) {
return parseFloat(getComputedStyle(panel).fontSize) * SELECT_ITEM_HEIGHT_EM;
}
ngOnDestroy() {
this.destroyed$.next(true);
this.destroyed$.complete();
this.infiniteScrollService.destroy();
}
}
MatSelectInfiniteScrollDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollDirective, deps: [{ token: i1.MatSelect }, { token: InfiniteScrollService }], target: i0.ɵɵFactoryTarget.Directive });
MatSelectInfiniteScrollDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: MatSelectInfiniteScrollDirective, selector: "[msInfiniteScroll]", inputs: { threshold: "threshold", debounceTime: "debounceTime", complete: "complete" }, outputs: { infiniteScroll: "infiniteScroll" }, providers: [InfiniteScrollService], ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollDirective, decorators: [{
type: Directive,
args: [{
selector: '[msInfiniteScroll]',
providers: [InfiniteScrollService]
}]
}], ctorParameters: function () { return [{ type: i1.MatSelect }, { type: InfiniteScrollService }]; }, propDecorators: { threshold: [{
type: Input
}], debounceTime: [{
type: Input
}], complete: [{
type: Input
}], infiniteScroll: [{
type: Output
}] } });
class MatSelectInfiniteScrollModule {
}
MatSelectInfiniteScrollModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
MatSelectInfiniteScrollModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollModule, declarations: [MatSelectInfiniteScrollDirective], imports: [MatSelectModule], exports: [MatSelectInfiniteScrollDirective] });
MatSelectInfiniteScrollModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollModule, imports: [MatSelectModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: MatSelectInfiniteScrollModule, decorators: [{
type: NgModule,
args: [{
declarations: [MatSelectInfiniteScrollDirective],
imports: [
MatSelectModule,
],
exports: [MatSelectInfiniteScrollDirective]
}]
}] });
/*
* Public API Surface of ng-mat-select-infinite-scroll
*/
/**
* Generated bundle index. Do not edit.
*/
export { MatSelectInfiniteScrollDirective, MatSelectInfiniteScrollModule };
//# sourceMappingURL=ng-mat-select-infinite-scroll.mjs.map