2

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?

1
  • You shouldn't be writing jQuery in your controller at all. It beats the purpose of using AngularJS Commented Jun 23, 2015 at 5:54

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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(…);
}]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.