简体   繁体   中英

Angular 2 scroll to top on route change not working

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?

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);
}

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)
        });
    }

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

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();
    });

  }
}
  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);
    }
  }

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);
    });
  }
}

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);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM