简体   繁体   中英

How can I scroll a div on a page without using jquery (what is the “Angular way”) and without scrolling the window?

I'm attempting to use the solution here to scroll a container to a certain position. Here's my version:

var wrapper = angular.element(document.getElementById('myWrapper'))[0];
var container = wrapper.querySelector('#myContainer');
var anchor = wrapper.querySelector('#myAnchorWithinTheContainer');
scrollContainerToAnchor(container, anchor);

...

function scrollContainerToAnchor(container, anchor) {
    var element = angular.element(anchor);
    angular.element(container).animate({scrollTop: element.offset().top}, "slow");
}

However, angular.element returns an array, so I don't see how that answer can work... but even if I correct it to the following:

function scrollContainerToAnchor(container, anchor) {
    var element = angular.element(anchor);
    angular.element(container)[0].animate({scrollTop: element[0].offset().top}, "slow");
}

the browser will still complain that "element[0].offset is not a function". So, I attempted to use getBoundingClientRect() instead:

function scrollContainerToAnchor(container, anchor) {
    var element = angular.element(anchor);
    angular.element(container)[0].animate({scrollTop: element[0].getBoundingClientRect().top}, "slow");
}

but then the browser gives me "Failed to execute 'animate' on 'Element': The provided double value is non-finite" (in my case, the "non-finite" value that it's complaining about is 3282.9375(?)).


Anyway, the fact that the above-linked answer has (as of today) 10 upvotes and no complaints in the comments suggests that I am missing something, not that the answer is incorrect... So, what am I missing ?


If there's a better way to scroll a div without using jQuery and without scrolling the whole page in addition to the div (I've already looked at $anchorScroll , but it scrolls both the window and the div), I'm up for other suggestions/techniques.

The answer referenced above requires jQuery. The offset function is part of jQuery. Angular makes use of jQuery Lite aka jqLite , which has no offset function.


To scroll the div without jQuery, I did the following:

HTML:

...
<div id="myScrollableDiv">
    ...
    <div id="elementIWantToScrollTo">...</div>
</div>
<div in-view="scrollableDivIsVisible()"></div>
...

Controller:

angular.module('myModule')
.controller('MyCtrl', ['$scope', function($scope) {
    ...

    var _hasBeenScrolled = false;
    $scope.scrollableDivIsVisible() {
        if (!_hasBeenScrolled) {
            document.getElementById('elementIWantToScrollTo').scrollIntoView();
            _hasBeenScrolled = true;
        }
    }
}]);

Note that scrollIntoView() causes both the window and the div to scroll (similar to $anchorScroll , but easier to use and doesn't add a hash tag to the URL). Since one of the requirements is to NOT scroll the window, I avoid that by using the in-view directive to detect when the bottom of my scrollable div is visible. Thus I only trigger scrollIntoView() when scrolling the window won't matter/is already complete. Then I use _hasBeenScrolled to ensure scrollIntoView() doesn't interfere with any scrolling that the user did (ie it's only auto scrolled once).


If you need to scroll a div based on some other trigger, rather than when the user first sees it, as was my need, then you can use the in-view directive to set a variable and then $scope.$watch() that variable before running your other trigger.


Maybe there's a better "Angular way" to do it, but the above gets the job done, and doesn't need jQuery.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM