Angular 5 Scroll to top on every Route click
I am using Angular 5. I have a dashboard where I have few sections with small content and few sections with so large content that I am facing a problem when changing router while going to top. Every time I need to scroll to go to top.
How can I solve this issue so that when I change the router, my view always stay at the top?
Solution 1:
There are some solutions, make sure to check them all :)
Option1:
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);
window.scroll({
top: 0,
left: 0,
behavior: 'smooth'
});
//or document.body.scrollTop = 0;
//or document.querySelector('body').scrollTo(0,0)
...
}
As the smooth scroll is not implemented well in Safari, 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);
}
}
Option2:
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.
Option3:
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 })
Solution 2:
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]
})
Solution 3:
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;
}
}