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">
tolceza
  • 91
  • 1
  • 1
  • 2

6 Answers6

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');
}
Zahema
  • 1,345
  • 2
  • 19
  • 35
  • 2
    "make sure component has a overflow property with values scroll or auto" solved my problem – KLMN Oct 19 '18 at 02:05
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.

Vega
  • 27,856
  • 27
  • 95
  • 103
  • @tolceza you should accept this answer as a solution! – Dmitry Grinko Oct 11 '19 at 19:52
  • 1
    `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? – rainversion_3 Nov 07 '19 at 14:32
  • @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 work – Vega Nov 07 '19 at 15:50
3

This should give you scroll events:

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

or

<div (scroll)="onScroll($event)"
Carsten
  • 4,005
  • 21
  • 28
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;
    }
}
jacek
  • 311
  • 3
  • 8
0

Could not make it work with scroll but with wheel:

@HostListener('window:wheel', ['$event'])
onWheel(event: MouseEvent) {
  // do what you want here
}
burkay
  • 1,075
  • 1
  • 10
  • 20
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.

Gabriel Messas
  • 159
  • 1
  • 5