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