angular-infinite-scroller
angular-infinite-scroller copied to clipboard
Proposal for update
trafficstars
It's a great example! I don't have time for creating PR, but I think you definitely should update project to RxJs6. Here is my proposal:
import { Directive, AfterViewInit, ElementRef, Input } from '@angular/core';
import { Observable } from 'rxjs';
import { fromEvent } from 'rxjs';
import { map, pairwise, filter, startWith, exhaustMap } from 'rxjs/operators';
interface ScrollPosition {
sH: number;
sT: number;
cH: number;
}
const DEFAULT_SCROLL_POSITION: ScrollPosition = {
sH: 0,
sT: 0,
cH: 0
};
@Directive({
selector: '[appScroller]'
})
export class ScrollerDirective implements AfterViewInit {
private scrollEvent$: Observable<any>;
private userScrolledDown$: Observable<any>;
private requestStream$: Observable<any>;
private requestOnScroll$: Observable<any>;
@Input()
scrollCallback;
@Input()
immediateCallback;
@Input()
scrollPercent = 70;
constructor(private elm: ElementRef) { }
ngAfterViewInit() {
this.registerScrollEvent();
this.streamScrollEvents();
this.requestCallbackOnScroll();
}
private registerScrollEvent() {
// this.scrollEvent$ = fromEvent(this.elm.nativeElement, 'scroll');
this.scrollEvent$ = fromEvent(window, 'scroll');
}
private streamScrollEvents() {
this.userScrolledDown$ = this.scrollEvent$.pipe(
map((e: any): ScrollPosition => ({
sH: e.target.scrollHeight,
sT: e.target.scrollTop,
cH: e.target.clientHeight
})),
pairwise(),
filter(positions => this.isUserScrollingDown(positions) && this.isScrollExpectedPercent(positions[1])));
}
private requestCallbackOnScroll() {
this.requestOnScroll$ = this.userScrolledDown$;
if (this.immediateCallback) {
this.requestOnScroll$ = this.requestOnScroll$.pipe(
startWith([DEFAULT_SCROLL_POSITION, DEFAULT_SCROLL_POSITION]));
}
this.requestOnScroll$.pipe(
exhaustMap(() => {
return this.scrollCallback();
}))
.subscribe((data) => { console.log(data); }, (err) => console.log(err));
}
private isUserScrollingDown = (positions) => {
return positions[0].sT < positions[1].sT;
}
private isScrollExpectedPercent = (position) => {
return ((position.sT + position.cH) / position.sH) > (this.scrollPercent / 100);
}
}