How to get on scroll events?

189,936

Solution 1

// @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

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

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

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

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());
Share:
189,936

Related videos on Youtube

Natanael
Author by

Natanael

Updated on November 10, 2021

Comments

  • Natanael
    Natanael over 2 years

    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?

    • AT82
      AT82 over 7 years
      Quite often you can apply events that as onclick, onsubmit etc. In angular the equivalent is usually just removing the 'on' and adding () from event names. e.g (click), (submit) etc... :)
  • Natanael
    Natanael over 7 years
    (scroll)="onScroll($event)" solved my problem well. Do you know if there's a equivalent binding to onresize of a element?
  • Günter Zöchbauer
    Günter Zöchbauer over 7 years
    No, browsers don't provide events for resize of elements, only for window resize ('window:resize'). You could implement ngDoCheck() and poll the size there. This can be expensive though, therefore if you can rely on less frequent events for polling the size using such an event instead would be preferred.
  • gtzinos
    gtzinos almost 7 years
    Hello, i just used your code in my component and last i added a (scroll)="onScrollEvent($event)" but i doesn't work.
  • Thomas Ducrot
    Thomas Ducrot almost 7 years
    (scroll)="onScrollEvent($event)" doesn't work, but my code is currently working on angular version 4.0.0, It triggers the scroll event
  • Katana24
    Katana24 over 6 years
    @GünterZöchbauer Can you tell from the event which direction the scroll is going? That is without examining and comparing the div scrollY value to the previous?
  • Günter Zöchbauer
    Günter Zöchbauer over 6 years
    developer.mozilla.org/en-US/docs/Web/Events/scroll lists the information provided by the event, which doesn't include anything about direction.
  • blueprintchris
    blueprintchris almost 6 years
    this works fine, no need to add (scroll)="onScrollEvent($event) in the HTML with this.
  • Günay Gültekin
    Günay Gültekin over 5 years
    In addition, This one is worked in Angular 6 --> stackoverflow.com/a/42547136/621951
  • Günter Zöchbauer
    Günter Zöchbauer over 5 years
    @GünayGültekin this one is to listen to scroll evens from an element, the one you linked to is for scroll events of the page/window.
  • Günter Zöchbauer
    Günter Zöchbauer over 5 years
    @Dmitry Grinko you don't always want window scroll events. Often you want scroll events from the current component. For example if you build a scrollable list or table component.
  • Mike D3ViD Tyson
    Mike D3ViD Tyson over 4 years
    remember to add import: import { HostListener } from '@angular/core';
  • Dominik
    Dominik about 4 years
    How to listen to an element scroll or "scrollTop" of an element? For example in a directive. Instead of "window". Window scroll only works on the body html scroll.
  • Günter Zöchbauer
    Günter Zöchbauer about 4 years
    See the last line in my answer above ;-)
  • Nick09
    Nick09 about 4 years
    <div (window:scroll)="onWindowScroll($event)">, clear, easy and works like a charm for me. Thanks mate!
  • Sir Papilonius
    Sir Papilonius almost 4 years
    How does setting a constant to a set of or statements work?
  • Stack Underflow
    Stack Underflow about 3 years
    @SirPapilonius the first one that's not falsy (0 or undefined etc.) will be used as the value.
  • Sir Papilonius
    Sir Papilonius about 3 years
    @StackUnderflow Ah, of course, that makes sense. Didn't think of that. Clever!
  • jcdsr
    jcdsr over 2 years
    However, is hostlistener the best to use? HostListener leads to excessive change detection as mentioned here. github.com/angular/angular/issues/16986 I do see a performance impact by using hostlistener, is not another way?
  • jcdsr
    jcdsr over 2 years
    HostListener leads to excessive change detection as mentioned here. github.com/angular/angular/issues/16986 I do see a performance impact by using hostlistener, is not another way?
  • jcdsr
    jcdsr over 2 years
    HostListener leads to excessive change detection as mentioned here. github.com/angular/angular/issues/16986 I do see a performance impact by using hostlistener, is not another way?
  • Günter Zöchbauer
    Günter Zöchbauer over 2 years
    @jcdsr without diving deeper into the issue and it's a long time ago I answered - usually you want change detection after an event, the main issue is the high frequency of scroll events (or resize events). If you use rxjs, you can use rate limiting and stuff which you can't with @HostListener()
  • jcdsr
    jcdsr over 2 years
    HostListener leads to excessive change detection as mentioned here. github.com/angular/angular/issues/16986 I do see a performance impact by using hostlistener, is not another way?