In Angular kann eine Komponente auf DOM Events reagieren. Ein Scroll Event kann eines dieser DOM Events sein. Bei den Scroll Events gibt es jedoch zwei Perspektiven: Scrollen innerhalb und außerhalb der Angular Komponente – wie beispielsweise das Scrollen innerhalb des Browserfensters. Zunächst schauen wir uns den ersten, leichteren Fall an.

Scroll Event: Scrollen innerhalb der Angular Komponente

Das Scroll Event ist ein DOM Event, das nativ durch Angular unterstützt wird. Dadurch ist die Implementierung analog zu einem Klick Event.

<div (scroll)="doSomething()" style="height: 80px; width: 70px; overflow: scroll;">
  <div style="height: 40px; background: gainsboro; margin: 5px; width: 40px;" *ngFor="let I of [1,2,3,4,5,6,7]">{{i}}</div>
</div>

Scroll Event: Scrollen außerhalb der Angular Komponente

Ein typischer Anwendungsfall ist das Schließen von überlappenden Hinweisen beim Scrollen. Diesen Fall kann jedoch nicht mit dem Scroll Event auf der Hinweis-Komponente verfolgen, weil diese typischerweise nicht durchscrollt wird. Hierfür ist eine Betrachtung auf das Browserfenster erforderlich. Der folgende Programmcode zeigt eine Implementierung eines Window-Scroll-Events.

<div (window:scroll)="doSomething()"></div>

Dieses Event ist jedoch nicht bei Angular-Komponenten und typischerweise auch nicht bei eigenen Komponenten verfügbar.

<!-- Fehler, das Window:Scroll ist nicht bei Angular Komponenten verfügbar -->
<ng-template (window:scroll)="doSomething()"></ng-template >

Bei dem Versuch dies dennoch zu probieren, zeigt der Browser die Fehlermeldung in der Log-Ausgabe:

[dt_quote type=”blockquote” font_size=”big” animation=”none” background=”plain”]

Uncaught Error: Template parse errors: Event binding window:scroll not emitted by any directive on an correctly and all directives are listed in the “@NgModule.declarations”.

[/dt_quote]

Die Lösung für diesen Fehler ist eine Hilfsdirektive. Diese kann an jede Komponente hinzugefügt werden und registriert das Scroll-Event selbst an dieser Komponente. Um Performace-Leaks zu vermeiden, muss dieses Event beim Zerstören der Komponente wieder entfernt werden.

import {Directive, EventEmitter, OnDestroy, OnInit, Output} from '@angular/core';
@Directive({
  selector: '[virtual7WindowScroll]'
})
export class WindowScrollDirective implements OnInit, OnDestroy {
  @Output() virtual7WindowScroll = new EventEmitter<null>();
  
  private scroll = (event: any) => {
    this.virtual7WindowScroll.emit(null);
  }
  
  ngOnInit() {
    window.addEventListener('scroll', this.scroll, true);
  }
  
  ngOnDestroy() {
    window.removeEventListener('scroll', this.scroll, true);
  }
}

Die Hilfsdirektive kann auch bei den HTML Elementen verwendet werden, auch wenn diese Window-Scroll-Events bereits native selber unterstützen. Dadurch hat der Entwickler ein einheitliches Vorgehen für diesen Verwendungszweck.

<div (virtual7WindowScroll)="doSomething()"></div>
<ng-template (virtual7WindowScroll)="doSomething()"></ng-template>

Durch diese Hilfsdirektive können eigene und Standard Angular Komponente auf Browser Scrollen reagieren.