Skip to content

Instantly share code, notes, and snippets.

@Muzammil-Bilwani
Created December 5, 2018 05:53
Show Gist options
  • Save Muzammil-Bilwani/333bef4f5d92c087ec5d8e19c067e2a5 to your computer and use it in GitHub Desktop.
Save Muzammil-Bilwani/333bef4f5d92c087ec5d8e19c067e2a5 to your computer and use it in GitHub Desktop.
For Infinite Scroll with RxJs
<!-- #scrollMe [scrollTop]="scrollMe.scrollHeight" remove this for normal scroll -->
<div class="comment-list" #scrollMe [scrollTop]="scrollMe.scrollHeight" infiniteScroll scrollPerecnt="20"
[immediateCallback]="true" [scrollCallback]="scrollCallback">
import { Directive, AfterViewInit, ElementRef, Input } from '@angular/core';
import { fromEvent } from 'rxjs';
import {
pairwise,
map,
exhaustMap,
filter,
startWith
} from 'rxjs/operators';
interface ScrollPosition {
sH: number;
sT: number;
cH: number;
};
const DEFAULT_SCROLL_POSITION: ScrollPosition = {
sH: 0,
sT: 0,
cH: 0
};
@Directive({
selector: '[infiniteScroll]'
})
export class InfiniteScrollDirective implements AfterViewInit {
ngAfterViewInit(): void {
this.registerScrollEvent();
this.streamScrollEvents();
this.requestCallbackOnScroll();
}
private scrollEvent$;
private userScrolledDown$;
private requestStream$;
private requestOnScroll$;
@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');
}
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) => {
// For downwards < will be used
return positions[0].sT > positions[1].sT;
}
private isScrollExpectedPercent = (position) => {
// For downwards > will be used
return ((position.sT + position.cH) / position.sH) < (this.scrollPercent / 100);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment