infinite scroll from the top (reverse) in AngularJS

11,592

You can try something like this: http://jsfiddle.net/mNFmf/4/

This will scroll to the bottom of the div:

$timeout(function() {
    raw.scrollTop = raw.scrollHeight;          
});    

And this will keep the div from scrolling up to the first item on the list:

var sh = raw.scrollHeight
scope.$apply(attr.whenScrolled);
raw.scrollTop = raw.scrollHeight - sh;

Update

To overcome the ajax request problem, try to use promises.

http://jsfiddle.net/mNFmf/8/

The loader would look something like this:

$scope.loadMore = function() {
  var deferred = $q.defer();

  // do ajax request here and after getting the result call:   
  deferred.resolve();

  return deferred.promise;
};

And on the other side:

loadMore.then(function() { 
  /* do whatever you want after the ajax request has been fulfilled */ 
});
Share:
11,592

Related videos on Youtube

Mark Nadig
Author by

Mark Nadig

SOreadytohelp

Updated on September 15, 2022

Comments

  • Mark Nadig
    Mark Nadig over 1 year

    I am trying to do a reverse infinite scroll. I have a comment list where I receive the last 10 most recent comments and want the user to be able to scroll up to retrieve the next 10 - similar to FB where it shows the most recent comments with a 'get previous' link, but via scroll event rather than a link.

    I started with http://jsfiddle.net/vojtajina/U7Bz9/ and tried to modify it to a reverse infinite scroll and pretty quickly ended up with something like this:

      function Main($scope, $timeout) {
        $scope.items = [];
    
        var counter = 0;
        $scope.loadMore = function() {
          // simulate an ajax request
          $timeout( function() {
            for (var i = 0; i < 5; i++) {
              $scope.items.unshift({id: counter});
              counter += 10;
            }}, 1000);
        };
    
        $scope.loadMore();
      }
    
      angular.module('scroll', []).directive('whenScrolled', ['$timeout', function($timeout) {
        return function(scope, elm, attr) {
          var raw = elm[0];
    
          $timeout(function() {
            raw.scrollTop = raw.scrollHeight;
          }, 1100);
    
          elm.bind('scroll', function() {
            // note: if test for < 100 get into infinite loop due to 
            // the delayed render
            if (raw.scrollTop === 0) {
              var sh = raw.scrollHeight
              scope.$apply(attr.whenScrolled);
              // the items are not loaded and rendered yet, so
              // this math doesn't work
              raw.scrollTop = raw.scrollHeight - sh;
            }
          });
        };
      }]);
      ​
    

    http://jsfiddle.net/digger69/FwWqb/2/

    The issue is that when the next 10 items are retrieved, they are added to the top of the list and the entire list re-renders, and the item that was at the of the list is completely scrolled out of view. In the fiddle item "40" is at the top and when you scroll (down slightly) and then up to trigger the scrolled, item "90" is at the top. I'm looking for a good strategy to keep "40" at the top of the scroll area after it has rendered.

    Note: In the fiddle I was able to get it to work by saving off the top li in the scroll event and calling scrollIntoView() until I added the timeout to simulate the ajax call. With the timeout the top li is scrolled into view before the request has come back and the new elements are rendered :/

    var top = elm.find("li")[0];
    scope.$apply(attr.whenScrolled);
    top.scrollIntoView();
    
  • Mark Nadig
    Mark Nadig over 11 years
    Thanks for the reply. Great ideas... what I am running into however is the problem that the scope.$apply(attr.whenScrolled) is an ajax call and so, the new items haven't been rendered yet when raw.scrollTop = raw.scrollHeigh - sh is run. I'll update the question and fiddle to demonstrate.
  • Mark Nadig
    Mark Nadig about 11 years
    It has been working for us - but our target platform is mobile. Note: just saw this come across my radar this weekend - github.com/BinaryMuse/ngInfiniteScroll
  • Michelle Tilley
    Michelle Tilley about 11 years
    @digger69 I'd be interested (as the author) to know if that was useful for you for this particular purpose.
  • Amal Antony
    Amal Antony over 10 years
    @BrandonTilley , hi Brandon, is it possible to use the ngInfiniteScroll for reverse infinte scrolling? Thanks!
  • justcode
    justcode about 7 years
    This saved me!!