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.