Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 5 Scroll to top on every Route click

There are some solutions, make sure to check them all :)


The router outlet will emit the activate event any time a new component is being instantiated, so we could use (activate) to scroll (for example) to the top:

app.component.html

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

app.component.ts

onActivate(event) {
    window.scroll(0,0);
    //or document.body.scrollTop = 0;
    //or document.querySelector('body').scrollTo(0,0)
    ...
}

Use, for exemple, this solution for a smooth scroll:

    onActivate(event) {
        let scrollToTop = window.setInterval(() => {
            let pos = window.pageYOffset;
            if (pos > 0) {
                window.scrollTo(0, pos - 20); // how far to scroll on each step
            } else {
                window.clearInterval(scrollToTop);
            }
        }, 16);
    }

If you wish to be selective, say not every component should trigger the scrolling, you can check it in an if statement like this:

onActivate(e) {
    if (e.constructor.name)==="login"{ // for example
            window.scroll(0,0);
    }
}

Since Angular6.1, we can also use { scrollPositionRestoration: 'enabled' } on eagerly loaded modules and it will be applied to all routes:

RouterModule.forRoot(appRoutes, { scrollPositionRestoration: 'enabled' })

It will also do the smooth scrolling, already. However this has the inconvenient for doing it on every routing.


An other solution is to do the top scrolling on router animation. Add this in every transition where you want to scroll to the top:

query(':enter, :leave', style({ position: 'fixed' }), { optional: true }) 

If you face this problem in Angular 6, you can fix it by adding the parameter scrollPositionRestoration: 'enabled' to app-routing.module.ts 's RouterModule:

@NgModule({
  imports: [RouterModule.forRoot(routes,{
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})

EDIT: For Angular 6+, please use Nimesh Nishara Indimagedara's answer mentioning:

RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
});

Original Answer:

If all fails, then create some empty HTML element (eg: div) at the top (or desired scroll to location) with id="top" on template (or parent template):

<div id="top"></div>

And in component:

  ngAfterViewInit() {
    // Hack: Scrolls to top of Page after page view initialized
    let top = document.getElementById('top');
    if (top !== null) {
      top.scrollIntoView();
      top = null;
    }
  }

Now there's a built in solution available in Angular 6.1 with scrollPositionRestoration option.

See my answer on Angular 2 Scroll to top on Route Change.