How to reset scroll position on a route change?

All we need is an easy explanation of the problem, so here it is.

I spend my first couple of hours with Angular JS and I am trying to write a SPA with it. However, on changing route, the scroll position remains at its current position after changing routes. This means that if someone read through half of the text on page two, this person will end up in the middle of page when two after changing to the second page. (Given that the pages are equally long.)

When I look for solutions I only find people asking for the opposite, i.e. they do not want to change the scrolling position once they change pages. However, I failed to reproduce even that. I wonder if the development of Angular JS got ahead of this and the sources I consulted were outdated.

I created a minimal version that demonstrates my problem (simply add two files sample1.html and sample2.html with random content to make it work.):

<!DOCTYPE html>
<html>
<head lang="en"><title>SPA sample</title></head>
<body data-ng-app="myApp">
<div style="position: fixed;">
  <a href="#/" rel="nofollow noreferrer noopener">Main</a>
  <a href="#/other" rel="nofollow noreferrer noopener">Tutorial</a>
</div>
<div data-ng-view=""></div>
<script src="https://code.angularjs.org/1.2.9/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.9/angular-route.min.js"></script>
<script>
    var myApp = angular.module('myApp', ['ngRoute']);
    myApp.config(function ($routeProvider) {
        $routeProvider
                .when('/', {
                    controller: 'noOp',
                    templateUrl: 'sample1.html'
                })
                .when('/other', {
                    controller: 'noOp',
                    templateUrl: 'sample2.html'
                })
                .otherwise({redirectTo: '/'});
    });
    myApp.controller('noOp', function ($scope) { });
</script>
</body>
</html>

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

As per the ngView documentation:

autoscroll(optional) string:

Whether ngView should call $anchorScroll to scroll the viewport after
the view is updated.

So all you have to do is change your ng-view call to turn on autoscroll like so:

<div ng-view autoscroll></div>

Method 2

After each route change there is an event fired on the $rootScope: $routeChangeSuccess. In the most basic scenario, just listen to this event and reset the scroll position to (0,0):

$rootScope.$on("$routeChangeSuccess", function(){
     window.scrollTo(0,0);
})

In a bit more advanced case you can store, for each url, the last position before leaving the url — then you should listen on: $routeChangeStart as well.
Very primitively, the storing could be made on the $rootScope itself, but I would prefer to use JS hash object and keep it as simple angular value instead.
If storing the last position should be made permanent (e.g. in localStorage), then you can consider use of angular service.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply