I\'m trying to get a quick nav to work correctly. It\'s floating on the side. When they click on a link, it takes them to that ID on the page. I\'m following this guide fro
very clear answer, using just ANGULARJS, no any JQUERY depends
in your html somewhere on the bottom <back-top>some text</back-top>
in your html somewhere on the top <div id="top"></div>
in your js:
/**
* @ngdoc directive
* @name APP.directive:backTop
<pre>
<back-top></back-top>
</pre>
*/
angular
.module('APP')
.directive('backTop', ['$location', '$anchorScroll' ,function($location, $anchorScroll) {
return {
restrict: 'E',
replace: true,
transclude: true,
template: '<span class=\'btn btn-mute pull-right\'><i class=\'glyphicon glyphicon-chevron-up\'></i><ng-transclude></ng-transclude></span>',
scope: {
},
link: function(scope, element) {
element.on('click', function(event) {
$anchorScroll(['top']);
});
}
};
}]);
This is a better directive in case you would like to use it:
you can scroll to any element in the page:
.directive('scrollToItem', function() {
return {
restrict: 'A',
scope: {
scrollTo: "@"
},
link: function(scope, $elm,attr) {
$elm.on('click', function() {
$('html,body').animate({scrollTop: $(scope.scrollTo).offset().top }, "slow");
});
}
}})
Usage (for example click on div 'back-to-top' will scroll to id scroll-top):
<a id="top-scroll" name="top"></a>
<div class="back-to-top" scroll-to-item scroll-to="#top-scroll">
It's also supported by chrome,firefox,safari and IE cause of the html,body element .
Thanks Andy for the example, this was very helpful. I ended implementing a slightly different strategy since I am developing a single-page scroll and did not want Angular to refresh when using the hashbang URL. I also want to preserve the back/forward action of the browser.
Instead of using the directive and the hash, I am using a $scope.$watch on the $location.search, and obtaining the target from there. This gives a nice clean anchor tag
<a ng-href="#/?scroll=myElement">My element</a>
I chained the watch code to the my module declaration in app.js like so:
.run(function($location, $rootScope) {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0;
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
})
The caveat with the code above is that if you access by URL directly from a different route, the DOM may not be loaded in time for jQuery's $target.offset() call. The solution is to nest this code within a $viewContentLoaded watcher. The final code looks something like this:
.run(function($location, $rootScope) {
$rootScope.$on('$viewContentLoaded', function() {
$rootScope.$watch(function() { return $location.search() }, function(search) {
var scrollPos = 0
if (search.hasOwnProperty('scroll')) {
var $target = $('#' + search.scroll);
var scrollPos = $target.offset().top;
}
$("body,html").animate({scrollTop: scrollPos}, "slow");
});
});
})
Tested with Chrome and FF