Search code examples
angularjsangular-ui-routerangular-ui-router-extras

How to 'remember' scroll position in angularJS w/ Ui.ROUTER


I have a project I'm using angularJS with ui.router and we have a list of events that can be really long (has infinite scroll) if a user clicks on an event to view details a back button is displayed however upon clicking back the scroll of the div resets back to the top! Looking for some suggestions as to if there is anything built in that I might leverage to remember this scroll position, I know theres the anchorscroll service but I am wondering if there isn't something more suited to stop angular from reseting the scroll positions on navigation?? as there are a few similar lists to this that need to remember their state when scrolled.. I've looked into and tried to implement ui-router-extras dsr and sticky but neither are working..
example at http://codedef.com/hapzis_poc/ . not a full proof but should be able to scroll down the events , click about and back and stay in same scroll position..


Solution

  • There is a conversation on the similar topic (ng-view) and the answer given by @br2000 worked for me.

    https://stackoverflow.com/a/25073496/3959662

    To make his directive work for ui-router do the following:

    1. Create new directive like this:

    (function () {
        'use strict';
    
        angular
            .module('your.module.directives')
            .directive('keepScrollPos', keepScrollPos);
    
        function keepScrollPos($route, $window, $timeout, $location, $anchorScroll, $state) {
    
            // cache scroll position of each route's templateUrl
            var scrollPosCache = {};
    
            // compile function
            var directive = function (scope, element, attrs) {
    
                scope.$on('$stateChangeStart', function () {
                    // store scroll position for the current view
                    if($state.$current)
                    { 
                        scrollPosCache[$state.current.templateUrl] = [$window.pageXOffset, $window.pageYOffset];
                    }
                 });
    
                scope.$on('$stateChangeSuccess', function () {
                    // if hash is specified explicitly, it trumps previously stored scroll position
                    if ($location.hash()) {
                        $anchorScroll();
    
                    // else get previous scroll position; if none, scroll to the top of the page
                    } else {
                        var prevScrollPos = scrollPosCache[$state.current.templateUrl] || [0, 0];
                        $timeout(function () {
                            $window.scrollTo(prevScrollPos[0], prevScrollPos[1]);
                    }, 0);
                }
            });
        };
    
        return directive;
    }
    })();
    

    2. Use it on the element you have the ui-view attribute, in my case:

    <div class="col-xs-12" ui-view keep-scroll-pos></div>