Autoscroll in Angular 2
I'm experiencing an issue with Angular 2 where changing from one route to another does not automatically scroll to the top of the new view. I realize that Angular 1 allowed for an autoscroll
property to be added to an HTML element, and others had come up with some simple javascript (such as window.scroll(0, 0)
) to force views to scroll to the top when loaded.
However, I am not sure how to accomplish this with Angular 2. Does anyone know how to achieve this?
update
Currently there is no automatic way.
See also Angular 2 typescript error when using subscribe function on new router (rc 1)
See also https://github.com/angular/angular/issues/6595#issuecomment-244232725
class MyAppComponent { constructor(router: Router) { router.events.subscribe(s => { if (s instanceof NavigationEnd) { const tree = router.parseUrl(router.url); if (tree.fragment) { // you can use DomAdapter const element = document.querySelector("#" + tree.fragment); if (element) { element.scrollIntoView(element); } } } }); } }
update
In the new router V3-beta.2 you can pass a fragment with router links and router navigation
<a [routerLink]="..." fragment="top">
it should scroll to it but also adds #top
to the URL (not tested myself yet)
Update
Original
There is an open issue covering this https://github.com/angular/angular/issues/6595
A workaround (mentioned in https://github.com/angular/angular/issues/6946)
Inject the router, subscribe to route changes and invoke the scroll to top:
>= RC.x
router.changes.subscribe() => {
window.scrollTo(0, 0);
});
beta
router.events
.filter(e => e instanceof NavigationEnd)
.subscribe(() => {
window.scrollTo(0, 0);
});
Has you can see here: https://angular.io/docs/ts/latest/api/router/index/Router-class.html#!#events-anchor, you have to use "router.events.subscribe" since Angular 2.0.0
So a good solution to automaticly scrool to the top of all page is to have a AppComponent like this:
import {Component} from '@angular/core';
import {Router, NavigationEnd} from "@angular/router";
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
constructor(private router: Router) {
router.events.subscribe((val) => {
if (val instanceof NavigationEnd){
window.scrollTo(0,0);
}
});
}
}
Newer RCs (>= RC.3) don't seem to expose a changes
Observable, it probably has since been renamed to events or routerEvents.
Their utterly "fantastic" docs don't seem to provide any information on what's doing what, so I guess you're in for a little Russian Roulette there. Or flip a coin or something.
From this answer, it seems the events
Observable returns events regarding navigation state:
router.events.subscribe(event:Event => { if(event is NavigationStart) { } // NavigationEnd // NavigationCancel // NavigationError // RoutesRecognized }
I had the same issue. Based on Gunter's answer I found that Angular's 2 RC.1 new router doesn't expose an Observable directly. Instead it has a changes
property for that purpose. The workaround for RC.1 is:
this._router.changes.subscribe(() => {
window.scrollTo(0, 0);
});