Vladimir Vladimir - 2 days ago 5
HTML Question

How to prevent scrolling to top after async update in Angular

After async request I add add a new element on top like this:

Array.prototype.unshift.apply(scope.conversation, conversation.data.message);


The problem is that after the element is added, the scroll position automatically moves to top. How can I maintain the same scroll position after my update?

I am using Angular1

Answer

Here is a sample of how to calculate the scrollTop after adding objects to the array.

The logic is:

  1. Save the scrollTop and the scrollHeight before adding.
  2. Add the items.
  3. Set the scrollTop by calc the delta of the height (by adding new items) and scroll to this height + the old scrollTop.

Keep it in your mind that there is a "jump" between the adding items and the new scrollTop. I don't think that you can over it unless you do some fadeOut/fadeIn or scrollTo with transition to cover this "jump".

Let me know if something not clear.

angular.module('app', []).
controller('ctrl', function($scope, $timeout) {
  $scope.index = 0;
  $scope.convert = function(arr) {
    for(var i = 0; i < arr.length; i++) {
      arr[i] = $scope.index++;
    }
    
    return arr;
  };
  
  $scope.items = $scope.convert(new Array(50));

  $scope.add = function() {
    var $container = $('.container');
    var container = $container[0];
    
    var scrollTop = $container.scrollTop();
    var oldHeight = container.scrollHeight;
    Array.prototype.unshift.apply($scope.items, $scope.convert(new Array(50)));
    $timeout(function(){
      var diff = container.scrollHeight - oldHeight;
      $container.scrollTop(diff + scrollTop);
    });
  }
});
.container {
  height: 100px;
  overflow-y:scroll;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div class="container">
    <div ng-repeat="item in items track by $index" class="scroll">
      Item {{item}}
    </div>
  </div>
  <button ng-click="add()">Add items</button>
</div>

Comments