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..
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>
For sticky states to work, you must not destroy the DOM element. Looking at your state structure, you are using the named ui-view body
for state home
, as per the ui-router-extras documentation. However, you then clobber that ui-view element when transitioning to about
state, which also uses the body
ui-view. This can be observed by inspecting the DOM.
.state('home', {
url: "",
deepStateRedirect: true,
sticky: true,
views: {
"body": {
templateUrl: 'templates/home.html'
},
"event_list@home": {
sticky: true,
templateUrl: "templates/eventList.html",
controller: "eventListCtrl"
}
}
})
.state('about', {
url: 'about',
views: {
"body": { // BAD, you just clobbered the sticky ui-view with this template
templateUrl: 'templates/about.html'
}
}
});
Make sure the sticky state's ui-view is not re-used. For your example, put about
state in the unnamed view.
.state('about', {
url: 'about',
templateUrl: 'templates/about.html'
});
index.html:
<div ui-view="body" ng-show="$state.includes('home')"></div>
<div ui-view></div>
js:
app.run(function($rootScope, $state) { $rootScope.$state = $state } );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With