Vladimir Vladimir - 9 days ago 5
AngularJS Question

How to not glue scroll to top after ajax

After ajax request I add add new element on top like this:

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


Problem is after element is added scroll automatically glue to top... How can I remove that behavior and leave scroll on same position after ajax request?

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>