Scroll to top of div in AngularJS?

71,559

Solution 1

I've had the same issue and I usually solve it with the following generic directive. It listens to a given event and whenever that event happens, it scrolls the element back to y = 0. All you need to do is $broadcast the event in your controller when your list changes.

angular.module("ui.scrollToTopWhen", [])
.directive("scrollToTopWhen", function ($timeout) {
  function link (scope, element, attrs) {
    scope.$on(attrs.scrollToTopWhen, function () {
      $timeout(function () {
        angular.element(element)[0].scrollTop = 0;
      });
    });
  }
});

Usage:

// Controller
$scope.items = [...];
$scope.$broadcast("items_changed")

// Template
<div id="myList" scroll-to-top-when="items_changed">

Solution 2

I would simply add a directive that watches the content of the DIV. It would then scroll to the top whenever the content changes! This solution does not require event processing (which I believe is unnecessary here).

mod.directive('scrollToTop', function(){
    return {
        restrict: 'A',
        link: function postLink(scope, elem, attrs) {
            scope.$watch(attrs.scrollToTop, function() {
                elem[0].scrollTop = 0;
            });
        }
    };
});

The html markup would then use the directive to trigger the scrolling thus:

<div class='myList' data-scroll-to-top='data.items.length'>
  <ul>
    <li data-ng-repeat='item in data.items'>{{item}}</li>
  </ul>
</div>

As you add items to the list, the DIV will scroll to the top! Here is a jsFiddle with working code: http://jsfiddle.net/pkgbtw59/89/

Solution 3

You can also use $anchorScroll as per the docs

// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');

// call $anchorScroll()
$anchorScroll();

You would need to wrap this within a $timeout:

$timeout(function() {
  $location.hash('myList');
  $anchorScroll();
})

Solution 4

I have faced the same issue with table body scrolling. I have resolved it in following way.

Here is my sample html.

<table id="rateplanmapping-scroll">
    <thead>
       <th></th>....
    </thead>
    <tbody >
        <tr ng-repeat="data in datas"> //this is the data
            <td></td>.....
        </tr>
    </tbody>
</table>

Here is the angular code to scroll to the top

<script>

  angular.element("#rateplanmapping-scroll tbody")[0].scrollTop=0; 

</script>

I hope it helps.
You can put this script in required function, so when particular things happen it get triggered automatically. Or can be attached to event also.

For div element this can be done in following way

http://plnkr.co/edit/0B4zrFTho6GYuPAS0S1A?p=preview

Thanks.

Share:
71,559
Max
Author by

Max

Updated on May 19, 2020

Comments

  • Max
    Max almost 4 years

    I am using AngularJS for a small web app and have encountered a problem. I am using ng-repeat to populate a list inside of a div. The div has a fixed height and is set to overflow-y: auto, meaning a scroll bar appears when the list is too big for the div. My problem is that when the list gets re-drawn, i.e. the data backing ng-repeat changes, the scroll bar does not reset to the top of the div. Instead, it stays at whatever position the scroll bar was at before the ng-repeat change. This is a very poor user experience. I've tried the following without any luck:

    <div id="myList">
      <ul>
        <li ng-repeat="item in items">{{item}}</li>
      </ul>
    </div>
    
    <a ng-click="switchItems()">Switch</a>
    
    <script>
    function MyApp($scope) {
      $scope.switchItems = function() {
        $('#myList').scrollTop();
        $scope.items = [1, 2, 3, 4]; // new items
      };
    }
    </script>
    
  • Max
    Max almost 10 years
    Thank you for this answer. This is a much more complete solution, but I wanted to add that there was a type that caused the problem in my original post. The correct jQuery command should have been $('#myList').scrollTop(0); Note the 0.
  • Elise
    Elise almost 10 years
    Nice catch, you should add it as an edit to your question so it's more visible :)
  • Stephanie
    Stephanie almost 9 years
    Very clean solution, thank you for this! When I used your directive, I got the following error with Angular 1.2.28: "directive is undefined". I managed to solve it by returning an object that contains the link function: angular.module("ui.scrollToTopWhen", []).directive("scrollToTopWhen", ['$timeout', function ($timeout) { return { link: function (scope, element, attrs) { ... } } }]);
  • Matthew Dolman
    Matthew Dolman over 7 years
    This is a jQuery answer not an Angular one.