You can try $("div#element"). load(function() {}) and place the element outside the document ready handler. Also, if a user scroll down the page, then leave the page, and go back to the page again, it should be a new start for him so it should start at the top. But now it also remembers the previous position.
on('scroll') and $scope. $apply to update a scope element on scroll. You'll receive more granularity on the scroll position because it's responding to the native scroll event, but you're going to be thrashing the angular scope by $applying that every time the handler fires.
I have a fiddle here that shows how to restore scroll position in the list view after a detail view; not encapsulated in a directive yet, working on that...
http://jsfiddle.net/BkXyQ/6/
$scope.scrollPos = {}; // scroll position of each view
$(window).on('scroll', function() {
if ($scope.okSaveScroll) { // false between $routeChangeStart and $routeChangeSuccess
$scope.scrollPos[$location.path()] = $(window).scrollTop();
//console.log($scope.scrollPos);
}
});
$scope.scrollClear = function(path) {
$scope.scrollPos[path] = 0;
}
$scope.$on('$routeChangeStart', function() {
$scope.okSaveScroll = false;
});
$scope.$on('$routeChangeSuccess', function() {
$timeout(function() { // wait for DOM, then restore scroll position
$(window).scrollTop($scope.scrollPos[$location.path()] ? $scope.scrollPos[$location.path()] : 0);
$scope.okSaveScroll = true;
}, 0);
});
The fiddle also shows fetching the list once, outside of 'ListCtrl'.
Below is another version of keep-scroll-pos directive. This version
Remembers scroll position of each templateUrl of your $routeProvider definition.
Respects hash tags, e.g., #/home#section-2, will scroll to #section-2 not previous scroll position.
Is easy to use, as it is self-contained, and stores scroll positions internally.
Example of html use:
<div ng-view keep-scroll-pos></div>
The code for keepScrollPos directive is below:
"use strict"; angular.module("myApp.directives", []) .directive("keepScrollPos", function($route, $window, $timeout, $location, $anchorScroll) { // cache scroll position of each route's templateUrl var scrollPosCache = {}; // compile function return function(scope, element, attrs) { scope.$on('$routeChangeStart', function() { // store scroll position for the current view if ($route.current) { scrollPosCache[$route.current.loadedTemplateUrl] = [ $window.pageXOffset, $window.pageYOffset ]; } }); scope.$on('$routeChangeSuccess', 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[$route.current.loadedTemplateUrl] || [ 0, 0 ]; $timeout(function() { $window.scrollTo(prevScrollPos[0], prevScrollPos[1]); }, 0); } }); } });
To disregard previously stored scroll position, and to force to scroll to the top, use pseudo hash tag: #top, e.g., href="#/home#top".
Alternatively, if you prefer to just always scroll to the top, use built-in ng-view autoscroll option:
<div ng-view autoscroll></div>
I have used the solution of @Joseph Oster in order to create a directive. I have also taken the liberty to update the answer to use:
as the other events are obsolete.
Fiddle is here: http://jsfiddle.net/empie/p5pn3rvL/
Directive source:
angular.module('myapp', ['ngRoute'])
.directive('autoScroll', function ($document, $timeout, $location) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.okSaveScroll = true;
scope.scrollPos = {};
$document.bind('scroll', function () {
if (scope.okSaveScroll) {
scope.scrollPos[$location.path()] = $(window).scrollTop();
}
});
scope.scrollClear = function (path) {
scope.scrollPos[path] = 0;
};
scope.$on('$locationChangeSuccess', function (route) {
$timeout(function () {
$(window).scrollTop(scope.scrollPos[$location.path()] ? scope.scrollPos[$location.path()] : 0);
scope.okSaveScroll = true;
}, 0);
});
scope.$on('$locationChangeStart', function (event) {
scope.okSaveScroll = false;
});
}
};
})
I haven't used it before, but angular has a $anchorScroll service. As to reloading the data, you could cache it using $cacheFactory, or store the data on a higher scope.
i created a directive that works on the window scroll ( it could updated to work on any element though )
html usage
<div ng-keep-scroll="service.scrollY">
<!-- list of scrolling things here -->
</div>
where "service.scrollY" MUST be a variable within a service. Services retain their state and values, controllers are recreated every time they load and clear their values so you cant use them to store persistent data. the controller has a scope variable pointing to the service.
directive js
app.directive('ngKeepScroll', function ($timeout) {
return function (scope, element, attrs) {
//load scroll position after everything has rendered
$timeout(function () {
var scrollY = parseInt(scope.$eval(attrs.ngKeepScroll));
$(window).scrollTop(scrollY ? scrollY : 0);
}, 0);
//save scroll position on change
scope.$on("$routeChangeStart", function () {
scope.$eval(attrs.ngKeepScroll + " = " + $(window).scrollTop());
});
}
});
Based on the great answer from br2000, I updated the directive code to work with ui-router. For states with same name but different params I serialize the $state.params object to make up a unique key in the scrollPosCache
object.
.directive("keepScrollPos", function($state, $window, $timeout, $location, $anchorScroll) {
// cache scroll position of each route's templateUrl
var scrollPosCache = {};
// compile function
return function(scope, element, attrs) {
scope.$on('$stateChangeStart', function() {
// store scroll position for the current view
if ($state.current.name) {
scrollPosCache[$state.current.name + JSON.stringify($state.params)] = [ $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.name + JSON.stringify($state.params)] || [ 0, 0 ];
$timeout(function() {
$window.scrollTo(prevScrollPos[0], prevScrollPos[1]);
}, 0);
}
});
}
})
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