Scroll to top on Angular Router navigation
Tags: angular, typescript, javascript
Published: 2019-06-06 07:13:48

*Originally published at [https://samvloeberghs.be](https://samvloeberghs.be/posts/scroll-to-top-on-angular-router-navigation) on November 19, 2016*

**Update (December 2018):** *This article has been updated to represent the newly available `ViewportScroller` class, available from Angular v7+. This class implementation wraps around the window object and only executes if the window object is available.*

When I was creating this blog and optimising it for mobile I experienced some default but not so user-friendly behaviour when navigating from one route to the other with Angular.

The problem is that content on mobile can go very deep below the initial viewport height. So when you're scrolling down and you press an internal link to another page, you'll be stuck at that height.

This is somewhat different from standard navigation between pages in a normal web-application, where the page reloads and you start from the top by default. In a S.P.A. this can easily be solved by scrolling to the top on navigation by using the native `window.scroll` function:

```js
window.scroll(0,0)
```

A navigation in routing in Angular 1 and ngRoute or even the ui-router can easily be detected by listening to the event `$routeChangeSuccess` or `$stateChangeSuccess`. So combining these 2 essentials gives us:

```ts
// ngRoute:
$rootScope.$on('$routeChangeSuccess', () => {
    $window.scroll(0,0);
});

// ui-router:
$rootScope.$on('$stateChangeSuccess', () => {
    $window.scroll(0,0);
});
```
I did not find anything similar in the documentation of the router of Angular so I went digging. The fact is that I'm using the [Angulartics2 plugin](https://github.com/angulartics/angulartics2) by [@luisfarzati](https://twitter.com/luisfarzati) to track you guys' behavior :). This is also done on navigation so there must be something similar going on at that plugin. The plugin BTW works great!

## Listening to navigation events in Angular

It seems that the Angular v2+ router has an `events` Observable property which you can subscribe on. Yes, it is as simple as that. Those events can be of any predefined type `NavigationStart`, `NavigationCancel`, `NavigationEnd` or `NavigationError`. In my case I only needed the `NavigationEnd`.

In the component that holds your navigation `router-outlet` you just need to setup the listener, something like this:

```ts
import { Component } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { ViewportScroller } from '@angular/common';

@Component({
  selector: 'sv-app',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent {

  constructor(
    readonly router: Router,
    readonly viewportScroller: ViewportScroller
  ) {

    router.events
      .filter(event => event instanceof NavigationEnd)
      .subscribe((event: NavigationEnd) => {
        // Angular v2-v6
        window.scroll(0, 0);
        // Angular v7+
        this.viewportScroller.scrollToPosition([0, 0]);
      });

  }
}
```

**Update (December 2018):** *This article has been updated to represent the newly available `ViewportScroller` class, available from Angular v7+. This class implementation wraps around the window object and only executes if the window object is available.*

And that was it! Be aware that the `window` object might not be available in every context, except the browser. [Check this awesome article](http://juristr.com/blog/2016/09/ng2-get-window-ref/) by [@juristr](https://twitter.com/juristr) to read more about why you might want to wrap your `window` object reference!

Please also be careful not to use these events to do business logic, like for example checking if you can navigate to a specific route based on some authentication rules. For those cases you may want to implement guards! More information about guards can be found in [this splendid article](http://blog.thoughtram.io/angular/2016/07/18/guards-in-angular-2.html) by [@PascalPrecht](https://twitter.com/PascalPrecht) of Thoughtram.

*Originally published at [https://samvloeberghs.be](https://samvloeberghs.be/posts/scroll-to-top-on-angular-router-navigation) on November 19, 2016*