How to configure AngularJs to scroll to anchor element specified in href with an #id?
The problem
The anchor link with a hash, ex. href="#recommanded" becomes url#/recommanded instead of url#recommanded so it will not scroll as expected. If angularjs library is not loaded, it works fine. In the statusbar when I move the cursor on top of the link the browser's statusbar correctly displays the link I'm about to be heading, but after clicking it will get transformed and will not scroll correctly. I'm not using angular's routes.
Snippets from my AngularJS code that might be interfering with scrolling / js location manipulations:
...
app.config([ '$httpProvider', '$compileProvider', function($httpProvider, $compileProvider) {
$compileProvider.debugInfoEnabled(false);
// Initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
// Disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
} ]);
...
app.directive('jumpForm', function($timeout) {
return {
restrict : 'A',
link : function(scope, elem) {
// set up event handler on the form element
elem.on('submit', function() {
$timeout(function() {
// find the first invalid element
var firstInvalid = elem[0].querySelector('.has-error');
// if we find one, set focus
if (firstInvalid) {
$('html, body').animate({
duration : 2000,
scrollTop : (firstInvalid.offsetTop + 100)
});
}
}, 200);
});
}
};
});
...
app.factory('httpResponseInterceptor', [ '$q', '$location', '$window', function($q, $location, $window) {
return {
response : function(response) {
if (response && response.data && response.data.errorCode == 'AUTHENTICATION_REQUIRED') {
var _context = $("body").attr("data-context");
var redirectUrl = _context + '/registration?msg=session_expired';
$window.location.href = redirectUrl;
return $q.reject(response);
}
return response;
}
}
} ]);
app.config([ '$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('httpResponseInterceptor');
} ]);
A call with hashtag:
<a href="#recommanded"> </a>
Trials and errors
Internal workarounds
anchorScroll
In the thread How to handle anchor hash linking in AngularJS it is advised to insert this snippet:
app.controller('TestCtrl', function($scope, $location, $anchorScroll) {
$scope.scrollTo = function(id) {
$location.hash(id);
$anchorScroll();
}
});
And in calling it:
<a ng-click="scrollTo('recommanded')">Foo</a>
This results in no error on the console but just the same behavior as before. Url is transformed no scrolling to anchor. Also I don't like the idea to end up having an ng-click function for this.
Appended my angularjs with:
app.run(function($rootScope, $location, $anchorScroll) {
//when the route is changed scroll to the proper element.
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute)
{
if($location.hash()) $anchorScroll();
});
});
and called it as
<a href="#/test#recommanded">Test/Foo</a>
Resulted in no error but scroll not working neither.
Some are hinting to just do a #/#recommanded in href. Use target="_self". None of them worked out for me.
External workaround solutions
Directive scrollTo
app.directive('scrollto',
function ($anchorScroll,$location) {
return {
link: function (scope, element, attrs) {
element.click(function (e) {
e.preventDefault();
$location.hash(attrs["scrollto"]);
$anchorScroll();
});
}
};
})
The html is looking like:
<a href="" scrollTo="recommanded">link</a>
This one actually works, but would prefer a solution where the call href="#recommended" just works. Or at least animate the scroll.
angular-scroll's du-smooth-scroll
Added duScroll to my angularApp.js: var app = angular.module('app', [ ..., 'duScroll' ]);
I have the angular-scroll.min.js file loaded on the page with angularApp.js without error.
I call <a du-smooth-scroll href="#recommended-to-you">recommanded</a>
for an existing div with that id. But it wont do anything, no js errors but will not move.
Tried duScroll module with adding explicit ease duration etc. settings, no errors but not working.