Angular 4 @HostListener Window scroll event strangely does not work in Firefox
Asked Answered
L

4

12

I'm using @HostListener('window:scroll', []) in Angular 4 app in order to add additional class to the header on scrolling. It works fine in Chrome but I noticed that in Firefox 54.0 (I think it's the last current version) the class is not added, it does not execute onWindowScroll() method at all. What can be the reason?

Here is a part of the code and a Plunker Demo (which by the way, also works fine in Chrome but not in Mozilla):

public isScrolled = false;
constructor(@Inject(DOCUMENT) private document: any) {}
@HostListener('window:scroll', [])
onWindowScroll() {
    const number = this.document.body.scrollTop;
    if (number > 150) {
        this.isScrolled = true;
    } else if (this.isScrolled && number < 10) {
        this.isScrolled = false;
    }
}


Any help would be much appreciated.

Landel answered 26/6, 2017 at 16:46 Comment(0)
M
11

I did face the same issue and resolved it by using window.scrollY rather than using this.document.body.scrollTop to make it work in Mozila Firefox. I know it is strange but it works.

Melodeemelodeon answered 24/7, 2017 at 6:26 Comment(0)
H
22

try this:

@HostListener('window:scroll', ['$event'])
onWindowScroll($event) {
    console.log("scrolling...");
}

I prefer this:

import { fromEvent } from "rxjs";

...

this.eventSubscription = fromEvent(window, "scroll").subscribe(e => {
    this.onWindowScroll();
});
Hotspur answered 26/6, 2017 at 18:2 Comment(1)
Thank you for your suggestions. I tried both - the first one didn't make any difference in Firefox, the second one though - that one with the Observable made the onWindowScroll event to be fired - "Scrolling.." is logged in the console. But still does not apply the class 'scrolled' to the header. I have to read more about Observables to think about a way for fixing that.Landel
M
11

I did face the same issue and resolved it by using window.scrollY rather than using this.document.body.scrollTop to make it work in Mozila Firefox. I know it is strange but it works.

Melodeemelodeon answered 24/7, 2017 at 6:26 Comment(0)
S
10

How i solved this

Works perfectly on Firefox, chrome and other browsers

Concept: You can listen to the properties of scrolling element that is body for now if you don't have any other scrolling element

@HostListener('window:scroll', ['$event']) onWindowScroll(e) {
    console.log(e.target['scrollingElement'].scrollTop)

    // Your Code Here

  }
Smattering answered 16/4, 2019 at 5:38 Comment(5)
Parameter 'e' implicitly has an 'any' type.Niggard
You can always define it's type onWindowScroll(e:Event) for reference check here what type Event Refers to developer.mozilla.org/en-US/docs/Web/API/EventSmattering
this should be the answer.Tolidine
Trying without success. Do we have to bind onto the outermost div like (scroll)="onWindowScroll($event)" should the template is a component within the root component?Desberg
You need to attach the scroll event to whatever element is scrollable & fits to your purpose. If you are looking for scroll on body element then event on body other wise on the element for which you want to detect scroll.Smattering
P
8

This Angular directive will work in both Chrome and Firefox:

import { Directive, Output, EventEmitter, HostListener, ElementRef, OnDestroy 
} from '@angular/core';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/fromEvent';

@Directive({
  selector: '[scroll]'
})
export class ScrollEventDirective implements OnDestroy {
  @Output() scrollPosition: EventEmitter<number> = new EventEmitter<number>
  ();

  private scrollEvent$;

  constructor(private el: ElementRef) {
    this.scrollEvent$ = Observable.fromEvent(this.el.nativeElement, 
    'scroll').subscribe((e: any) => {
      this.scrollPosition.emit(e.target.scrollTop);
    });
  }

  ngOnDestroy() {
    this.scrollEvent$.unsubscribe();
  }
}

Using the directive on a DIV element:

<div scroll (scrollPosition)="scrollChanged($event)">...</div>
Particularly answered 13/1, 2018 at 8:23 Comment(1)
Update: RxJs 6+ #50572050Convivial

© 2022 - 2024 — McMap. All rights reserved.