Window scroll event using @HostListener not working
Asked Answered
C

6

9

I have problem making sticky header when scrolling down, in an Angular 4 application. Scroll event can't be detected.

Header is placed in the layout component, and the content I want to be scrolling is placed in routes component. May that be the problem?

This is the code I implemented.

In layout.component.ts

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

import { DOCUMENT } from "@angular/platform-browser";

@Component({

  selector: 'app-layout',

  templateUrl: './layout.component.html',

  styleUrls: ['./layout.component.css']
})

export class LayoutComponent implements OnInit {

  public navIsFixed: boolean = false;

  constructor(public router: Router, @Inject(DOCUMENT) private document: any) { }

  @HostListener('window:scroll', [ ])

    onWindowScroll(){
      const number = window.pageYOffset || 
      document.documentElement.scrollTop || 
      document.body.scrollTop || 0;
      if (number > 50) {
        this.navIsFixed = true;
      } else if (this.navIsFixed && number < 10) {
      this.navIsFixed = false;
      }
    }
}

In layout.component.html

<div [class.fixed]="navIsFixed" class="header">
Coretta answered 29/8, 2017 at 11:22 Comment(4)
What if you define it in the top-level component? app.component.ts (i assume your router-outlet is there...)Bever
<router-outlet></router-outlet> is placed in layout.component.html @BeverCoretta
did you find a solution? I have the same issue @CorettaCorrinnecorrival
@Corrinnecorrival please see the answer above, the main component must have the overflow property. Note : don't try to add this property with DevTools, in that case that would not workScope
O
8

I just had the same problem, all what I had to do was to make sure that the component element is actually what is scrolling & that it has a overflow property with values scroll or auto.

Otherwise just this worked:

@HostListener('scroll')
  public asd(): void {
  console.log('scrolling');
}
Octant answered 10/6, 2018 at 20:35 Comment(1)
"make sure component has a overflow property with values scroll or auto" solved my problemColloquy
A
4

Your layout must be the source of the issue. The scroll event works only when the the component template element can actually scroll.

Make sure the div has overflow property set to scroll. Also, change the div dimensions so the scroll could trigger.

In order to make it work, I would suggest to make it to the directive and set to a div that has 100vh in height and 100vw in width.

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

@Directive({ selector: '[trackScroll]' })
export class TrackScrollDirective {
    constructor(private el: ElementRef) {
    }

    @HostListener('document:scroll', [])
    onScroll(): void {
         console.log('I am scrolled');
    }
}
 

See this stackblitz that I made.

Ainu answered 30/8, 2017 at 21:26 Comment(3)
@Coretta you should accept this answer as a solution!Windowpane
Your layout must be the source of the issue. Can you elaborate what this means? If I can't give height and width as 100vw how can I track if scroll action is performed on component?Commensurable
@rainversion_3, I wasn't clear there for sure. Does the div have overflow:scroll on it? You don't need the full width and height for the scroll to workAinu
B
3

This should give you scroll events:

@HostListener('scroll', ['$event'])
onScroll(event) {
  ...
}

or

<div (scroll)="onScroll($event)"
Bever answered 29/8, 2017 at 11:50 Comment(3)
Thanks but it is not even detecting the scroll event.Coretta
Works on Chrome, not on Firefox.Tracheo
@Bever this gives Maximum call stack size exceeded errorFoamflower
N
0

I have the same issue, I added this to "nav.component":

@HostListener('window:scroll', [])
onWindowScroll() {
    console.log(window.scrollY);

    if (window.scrollY > 90) {
        this.isSticky = true;
    } else {
        this.isSticky = false;
    }
}
Nonrecognition answered 25/6, 2021 at 14:57 Comment(0)
C
0

Could not make it work with scroll but with wheel:

@HostListener('window:wheel', ['$event'])
onWheel(event: MouseEvent) {
  // do what you want here
}
Cockahoop answered 19/4, 2023 at 15:30 Comment(1)
Which would not work on touch devices, or using the scrollbar, or keyboard navigation.Hinojosa
D
0

In my case, the issue was a simple overflow-x: hidden placed on the <html> scope. Removing and replacing it right under, on the <body> scope, fixed the problem, while keeping my overflow configuration.

Every component can detect scroll events, regardless of hierarchy. There is no need to worry about parent/child relations.

Domiciliary answered 6/7, 2023 at 23:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.