Skip to content
Aprende Angular de forma rápida y efectiva  Ver curso

Domina el evento scroll en Angular

Escuchar el evento scroll en Angular es más sencillo de lo que parece. Te voy a explicar las distintas maneras que te ofrece Angular para conseguirlo con apenas 2 líneas de código.

Scroll dentro de un componente

Imagina que tienes un elemento cuyo contenido es mayor que su altura, de forma que puedes hacer scroll en su interior. Vamos a llamar a este elemento <scrollable-component>.

scrollable element in angular

Angular te ofrece 2 formas muy sencillas para atender a ese evento scroll del componente.

Tip: Para que un componente entienda que se está haciendo scroll en su interior, es necesario que su propiedad CSS display sea tipo block-level, es decir: block, inline-block, grid o flex.

1) suscripción externa, desde el template padre

Puedes atender ese evento de scroll desde fuera del componente, es decir, desde su componente padre.

Solo necesitas usar un event binding sobre su propiedad scroll, como si de un click se tratara. Así:

<scrollable-component (scroll)="doSomethingOnScroll($event)">
    <item></item>
    <item></item>
    <!-- some more items -->            
</scrollable-component>

De este modo, cuando estés haciendo scroll dentro de <scrollable-component>, se llamará al método doSomethingOnScroll() del componente que lo contiene.

2) suscripción interna, desde el componente

Puedes suscribirte al evento de scroll del componente desde su propio controlador, usando un HostListener. Así:

import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'scrollable-component',
  templateUrl: './scrollable.component.html',
  styleUrls: ['./scrollable.component.css']
})
export class ScrollableComponent {

  @HostListener("scroll", ['$event'])
  doSomethingOnInternalScroll($event:Event){
    let scrollOffset = $event.srcElement.scrollTop;
    console.log("scroll: ", scrollOffset);
  }}

}

De este modo, a cada evento de scroll del componente ScrollableComponent, se ejecutará el método doSomethingOnInternalScroll().

OFERTA
Curso

Componentes Angular Nivel PRO

Domina los componentes de Angular (Angular 2/4/5+) como un experto y crea componentes técnicamente brillantes.
Idioma: Español
23 €110 €

Evento scroll global

Hasta ahora veías como suscribirte a un evento de scroll limitado a un componente, pero por supuesto, podrías querer escuchar el evento scroll global, el típico window.scroll, para que nos entendamos.

Angular te da acceso al evento scroll global de forma análoga a los dos ejemplos anteriores, mediante window:scroll.

De este modo puedes:

1) Suscribirte a window:scroll desde el template

Se me hace un poco extraño, pero puedes suscribirte desde un elemento cualquiera del template, así:

<div (window:scroll)="doSomethingOnWindowScroll($event)">       
</div>
<!-- some more stuff -->    

2) Suscribirte a window:scroll desde el componente

Para mi esta opción tiene bastante más sentido: Suscribirte con un @HostListener desde el componente en que quieres escuchar el evento de scroll global:

import { Component, HostListener } from '@angular/core';

@Component({
  selector: 'my-component',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.css']
})
export class MyComponent {

  @HostListener("window:scroll", ['$event'])
  doSomethingOnWindowsScroll($event:Event){
    let scrollOffset = $event.srcElement.children[0].scrollTop;
    console.log("window scroll: ", scrollOffset);
  }

}

Reflexiones personales

Angular te ofrece de partida unos mecanismos muy sencillos para escuchar eventos de scroll. ¿Pero que pasa si quieres reducir la frecuencia con la que se llama el evento? Ahí amigo, la cosa se complica.

En próximos artículos explicaré como crear un servicio de scroll con debouncing para evitar interrupciones demasiado frecuentes durante el scroll.

¿Te ha gustado este artículo? No te cortes, déjame un comentario y ayúdame a compartirlo 😉

Published inAngular

11 Comments

  1. Saludos excelente trabajo el que realizas, oye tal vez puedas ayudarme estoy realizando mi aplicación pero tengo un problema o dos el primero es que cuando voy de una pagina a otra no va al inicio de la pagina es decir si me encuentro en el home y luego hago link a servicio me lleva hasta la mitad o depende de donde me encuentre en el home, no se si me explico quisiera me llevara al inicio de la pagina servicio y así con el resto.El otro es que cuando mi app carga el slider esta bien pero al explorar la app y regresar al home ya el slider no carga hay una manera de recarga la pagina todo esto en Angular gracias de antemano

  2. Martín Martín

    Para el scroll usa window.scrollTo(0, 0);

  3. Johan Nieto Johan Nieto

    Saludos Enrique , gracias por el tutorial, sin embargo en la línea

    let scrollOffset = $event.srcElement.children[0].scrollTop;

    el compilador me indica:
    La propiedad ‘children’ no existe en el tipo ‘EventTarget’.

    Sabes porqué puede ser?

    • julianprog julianprog

      Me pasa lo mismo que a Johan Nieto, alguien sabe por que ?

    • Alvaro Alejandro Pavon Torres Alvaro Alejandro Pavon Torres

      Hola me pararece que esto sucede porque srcElement esta depreciado

      • Karla Karla

        Esto tal vez tiene que ver con el tipado de TS, no recuerdo bien, pero creo que especificando el se resuelve

  4. Victor Ascencio Hernández Victor Ascencio Hernández

    Hola!,
    Yo estoy intentando implementar un botón que haga el scroll hasta top, pero lo estoy haciendo desde una directiva, ya que la idea es usar este botón en otros componentes, desafortunadamente el evento scroll no me está regresando nada aunque haga scroll :/.

    button: HTMLElement;
    ngAfterViewInit() {
    this.button = document.createElement(‘button’);
    this.button.classList.add(‘scroll-to-top’);
    this.button.addEventListener(‘click’, () => {
    this.elRef.nativeElement.scrollIntoView( {behavior: ‘smooth’} ); // con esto hago scroll hasta el div donde anadí la directiva
    });
    this.elRef.nativeElement.appendChild(this.button);
    this.elRef.nativeElement.addEventListener(‘scroll’, () => console.log(‘estoy haciendo scroll’);
    }

    • Karla Karla

      Hola! Yo me cree un comp bien sencillo con un tag button, al que simplemente agrego este metodo al dar click:
      toTheTop() {
      document.body.scrollTop = 0;
      document.documentElement.scrollTop = 0;
      }

      • Daniel Daniel

        Gracias Karla, tu idea me funciono mucho para lo que necesitaba

  5. Hola alguien ya corrigio el error del deprecado? $event.srcElement.children[0].scrollTop, srcElement is deprecated

  6. Hola, para los que aun tienen problemas, encontre esta otra solucion, me sirvio excelente:

    @HostListener(‘window:scroll’, [‘$event’])
    track(event) {
    console.debug(«Scroll Event», window.pageYOffset );
    }

    Saludos

Deja un comentario