Reputation: 2485
I want users to smoothly scroll to the top of the page when they click a certain button. I use jQuery's .animate
for this. However, whatever I try, Angular warns me that I cannot access DOM elements outside the scope.
This is what I tried:
Template:
<button ng-click="action()">
Controller:
$('html, body').animate({ scrollTop: 0 }, 'slow')
This works but Angular gives the error.
Anybody ideas how to do this the right way?
Upvotes: 2
Views: 6120
Reputation: 11548
On your controller simply continue with having only information about the action and not the scroll. as the scroll is an enhancement:
$scope.buttonAction = function () {
console.log('button action');
}
In your view use the button normally but now define a directive for it to add additional scroll behaviour:
<button scrollup ng-click="buttonAction()">Click me</button>
and finally your scrolling stuff should be in that scrollup directive:
app.directive('scrollup', function ($document) {
return {
restrict: 'A',
link: function (scope, elm, attrs) {
elm.bind("click", function () {
// Maybe abstract this out in an animation service:
// Ofcourse you can replace all this with the jQ
// syntax you have above if you are using jQ
function scrollToTop(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(function () {
element.scrollTop = element.scrollTop + perTick;
scrollToTop(element, to, duration - 10);
}, 10);
}
// then just add dependency and call it
scrollToTop($document[0].body, 0, 400);
});
}
};
});
Now you will be able to add whatever action you need in your controllers but also have the jumping upo behaviour by adding the directive.
Upvotes: 4
Reputation: 2996
Why not scroll to the top of the element
the scope
is working on? If you have something like
<div ng-controller="SomeCtrl">
…
</div>
And in the controller:
app.controller('SomeCtrl', ['$scope', '$element', function ($scope, $element) {
$($element).animate(…);
}]);
Upvotes: 0