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 haben Entwickler:innen 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.