How to get on scroll events?
HtmlCssAngularTypescriptScrollbarHtml Problem Overview
I need to get scroll events from a div with overflow: scroll in my Angular 2 app.
It seems onscroll event do not works on Angular 2.
How could I achieve that?
Html Solutions
Solution 1 - Html
// @HostListener('scroll', ['$event']) // for scroll events of the current element
@HostListener('window:scroll', ['$event']) // for window scroll events
onScroll(event) {
...
}
or
<div (scroll)="onScroll($event)"></div>
Solution 2 - Html
You could use a @HostListener decorator. Works with Angular 4 and up.
import { HostListener } from '@angular/core';
@HostListener("window:scroll", []) onWindowScroll() {
// do some stuff here when the window is scrolled
const verticalOffset = window.pageYOffset
|| document.documentElement.scrollTop
|| document.body.scrollTop || 0;
}
Solution 3 - Html
for angular 4, the working solution was to do inside the component
@HostListener('window:scroll', ['$event']) onScrollEvent($event){
console.log($event);
console.log("scrolling");
}
Solution 4 - Html
Listen to window:scroll
event for window/document level scrolling and element's scroll
event for element level scrolling.
window:scroll
@HostListener('window:scroll', ['$event'])
onWindowScroll($event) {
}
or
<div (window:scroll)="onWindowScroll($event)">
scroll
@HostListener('scroll', ['$event'])
onElementScroll($event) {
}
or
<div (scroll)="onElementScroll($event)">
@HostListener('scroll', ['$event'])
won't work if the host element itself is not scroll-able.
Examples
Solution 5 - Html
Alternative to @HostListener
and scroll output on the element I would suggest using fromEvent from RxJS since you can chain it with filter()
and distinctUntilChanges()
and can easily skip flood of potentially redundant events (and change detections).
Here is a simple example:
// {static: true} can be omitted if you don't need this element/listener in ngOnInit
@ViewChild('elementId', {static: true}) el: ElementRef;
// ...
fromEvent(this.el.nativeElement, 'scroll')
.pipe(
// Is elementId scrolled for more than 50 from top?
map((e: Event) => (e.srcElement as Element).scrollTop > 50),
// Dispatch change only if result from map above is different from previous result
distinctUntilChanged());
Solution 6 - Html
To capture scroll events and see which of the scroll event is being called, you have to use host listener who will observe the scroll behavior and then this thing will be detected in the function below the host listener.
currentPosition = window.pageYOffset;
@HostListener('window:scroll', ['$event.target']) // for window scroll events
scroll(e) {
let scroll = e.scrollingElement.scrollTop;
console.log("this is the scroll position", scroll)
if (scroll > this.currentPosition) {
console.log("scrollDown");
} else {
console.log("scrollUp");
}
this.currentPosition = scroll;
}
Solution 7 - Html
Check the multiple examples as mention on this URL.
I will recommend the method 3,
https://itnext.io/4-ways-to-listen-to-page-scrolling-for-dynamic-ui-in-angular-ft-rxjs-5a83f91ee487
@Component({
selector : 'ngx-root',
templateUrl : './app.component.html',
styleUrls : [ './app.component.scss' ],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppComponent implements OnDestroy {
destroy = new Subject();
destroy$ = this.destroy.asObservable();
constructor() {
fromEvent(window, 'scroll').pipe(takeUntil(this.destroy$))
.subscribe((e: Event) => console.log(this.getYPosition(e)));
}
getYPosition(): number {
return (e.target as Element).scrollTop;
}
ngOnDestroy(): void {
this.destroy.next();
}
}
However Method 4 is not bad.