19

I am trying to scroll to the top of my page on my angular 2 site when the route changes, I have tried the following, but nothing happens, when I change the route from one page to another, the page is scrolled to where it was on the first page:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
    selector: 'my-app',
    template: '<ng-content></ng-content>',
})
export class MyAppComponent implements OnInit {
    constructor(private router: Router) { }

    ngOnInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }
}

What am I doing wrong?

6
  • Try setTimeout(function () {window.scrollTo(0, 300);},2) Commented Nov 7, 2018 at 2:37
  • Nope, that did not work, I get no errors in my console log. Commented Nov 7, 2018 at 3:21
  • I tried that it worked for me. Other option is using jquery $('#content').animate({ scrollTop: 20 }, 200). Commented Nov 7, 2018 at 3:23
  • Still does not work, this is annoying Commented Nov 7, 2018 at 3:47
  • 1
    Can you provide a stackblitz showing the problem? Commented Nov 13, 2018 at 0:39

6 Answers 6

14
+100

The router will emit an event when a new component gets loaded in the <router-outlet> so you can attach an event to it.

So in your component with <router-outlet> use:

<router-outlet (activate)="scrollTop($event)">

and then in the same component where you placed <router-outlet> add the following method:

scrollTop(event) {
  window.scroll(0,0);
}
Sign up to request clarification or add additional context in comments.

3 Comments

I tried this, scrollTop is being called on every page, but its not scrolling to the top of the page.
Actually, this does work, but only when I remove height: 100% to the body
This answer appears to be correct, gonna do some testing on it first.
3

Wait for the component to initialized component before you start scrolling. So better to put this code under ngAfterViewInit function.

 ngAfterViewInit() {
        this.router.events.subscribe((evt) => {
            if (!(evt instanceof NavigationEnd)) {
                return;
            }
            window.scrollTo(0, 0)
        });
    }

4 Comments

Trying this now.
Put the logs before window.scrollTo(0, 0) and check if getting executed. I am doubting return statement is getting executed.
I put a console.log right before window.scrollTo(0, 0) and it is not being executed
Wait my bad, the console log is getting executed.
3

This similar issue was faced by me which was due to the style applied to body. i.e.

body {
    height: 100%;
    overflow-x: hidden;
}

If I removed this style then my layout was badly affected.

Instead of removing style I tried below solution and it worked for me...

Solution:

export class AppComponent implements OnInit {


  constructor(private router: Router, private changeDetect: ChangeDetectorRef) {
  }

  ngOnInit() {
    this.router.events.subscribe((evt) => {
      if (!(evt instanceof NavigationEnd)) {
        return;
      }
      // Change height:100% into auto
      $('body').css('height', 'auto');
      // Successfully scroll back to top
      $('body').scrollTop(0);
      // Remove javascript added styles
      $('body').css('height', '');
      this.changeDetect.detectChanges();
    });

  }
}

Comments

2
  constructor(
    private router: Router,
    private ngZone: NgZone) {
    router.events.subscribe((event: RouterEvent) => {
      this._navigationInterceptor(event);
    });
  }

  private _navigationInterceptor(event: RouterEvent): void {
    if (event instanceof NavigationStart) {
    }
    if (event instanceof NavigationEnd) {
    window.scrollTo({
     top: 0
    });
  // or,  window.scroll(0,0);
    }
  }

Comments

2

This solution works perfectly in my project:

export class AppComponent  {
  constructor (
    private _router: Router,
  ) {
    this._subscribeRouteEvents();
  }

  private _subscribeRouteEvents (): void {
    this._router.events.subscribe(e => {
      if (!(e instanceof NavigationEnd)) return;
      window.scrollTo(0, 0);
    });
  }
}

Comments

0

The only solution that works for me on Angular 10.2.x is using setTimeout for 190ms and no less! If I set timer below 190ms, scrolling is not work!

When I set the timer to 300ms, then I can see how, after routing, the page first scrolls by Angular router to a position I don't need, and then page scrolls to 0, as it should. I still do not understand why Angular makes unnecessary scrolling after route to the page.

I tried different suggested solutions. For example, such as changing the value of the scrollPositionRestoration property and performing forced scrolling in the AfterViewInit hook, and changing the global height of body tag, but only this helped. Most likely this is some kind of error in the Angular 10.2.x router

constructor(
  private router: Router,
) {
  router.events.subscribe(event => {
  if (event instanceof NavigationEnd) {
    setTimeout(() => {
      document.documentElement.scrollTop = 0; // || window.scrollTo(0, 0);
    }, 190);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.