Infinite scroll for both directions


#1

Hello,

I watched this link that provides Ionic solution for infinite-scrolling: LINK

However I’m looking for the way for both directions scrolling.

For example I have Contacts list with more then 800 items (text + image).

Its pretty nice to show on start 7-8 items and append on scrolling. But if User will scroll to the end of list - I have big problem of performance even on strong devices.

I tried THIS solution but somehow it mixes with Ionic directives and I need investigate where is a problem.

Right now I use THIS option but sounds like I need to upgrade the code as well.

Any suggestions?

Thanks,


Scrolling is really lag
#2

Can you explain “both directions”? Horizontal and vertical?

If you can give us a sample of the code, I can put on my device and test. Without seeing what you have right now, it’s going to be hard to help.

On my app, I also list all contacts. However, I’m not doing infinite-scrolling - just a long list and with no images. With about 400 contacts, it’s reasonably performant. I’m using bind-once.


#3

Both directions means list size equals only to what we actually see 7-8 items. When I scroll down, we populate list. So when I move to the end of list, I show actually list of 600-700 items and it “kills” the GUI.

… just a long list and with no images. …

Well, I need to show contacts with images and more then 40 items I see some delay on scrolling.

Anyways what I try to do:

when scroll down add 20 new elements and remove 20 old ones.
when scroll up add 20 old elements and remove 20 new.

Its like shifting. The ngRepeat is invoked only on 20 elements at all.

HTML

<view title="'Pet Information'">
  <content has-header="true" has-tabs="true" on-infinite-scroll="loadMore">
    <list>
      <item ng-repeat="pet in pets" type="item-text-wrap" href="#/tab/pet/{{pet.id}}">
        <h3>{{pet.title}}</h3>
        <p>{{pet.description}}</p>
        </item>
      </item>
    </list>
  </content>
</view>

JS

.controller('PetIndexCtrl', function($scope, PetService) {  
  $scope.pets_all = PetService.all();
  $scope.pets = [];
  // Add just 10 pets at the first time
  var count = 0;
  for (var i = 0; i < 10; i++) {
    $scope.pets.push($scope.pets_all[i]);
    count++;
  };

  $scope.loadMore = function() {    
    var curr_count = count;
      for (var i = curr_count; i < curr_count + 10; i++) {
        if (i < $scope.pets_all.length) {
          $scope.pets.push($scope.pets_all[i]);
          count++;
        } else {
          return;
        }   
     }
  }
})

#4

I agree that this is the right idea. I’m planning on implementing something similar myself soon if I can’t find an existing solution. Simply appending endlessly is not performant for long lists. Especially if images are involved.

Here’s the rough idea I have in mind:
To maintain consistency in the behavior of scrolling for the user (no jumping around), previous elements that have gone off screen above (perhaps outside a reasonable buffer area on either side of the viewport) could be removed from the dom temporarily. But, to maintain scrolling positions, the first non-removed element will be given a top margin equal to its previous top position. If the user scrolls back up, the margin is reduced and moved up the chain to the topmost reintroduced element. As they scroll back up, the same methodology could be used to remove dom elements below, using a margin-bottom to maintain scrollbar size. Or, for simplicity, elements below the fold could simply be removed and the original infinite scroll could act once again if they reverse scrolling direction yet again.

Edit: I just found this implementation on the web which looks quite similar to what I describe above. They use a spacer/header div to push everything else down, rather than using margin-top. And they maintain a previous, current and next page to keep things smooth in transition. It depends on jquery, but looks to be quite solid.

http://airbnb.github.io/infinity/
http://airbnb.github.io/infinity/demo-on.html

It would be wonderful if the ionic infinite scroll directive had built in support for such a concept. In the meantime, I’ll post here if I manage to implement something that works well in the next week or so.


#5

I think this: https://github.com/driftyco/ionic/issues/65 is the issue for this behavior.


#6

And inside that issue # 65 is this link:


#7

Thank you @elm and @Calendee.

For lazy staff here is a PLUNKER . But for Ionic it will not work because ionic list based on device touch when ui-table-view is based on scrolling.


#8

@shoustin I would suggest using ReactJS for rendering performance critical views. I have tried it and Performance when from 2000ms to under 300ms for a table with 5000 rows. It plays nicely with AngularJS and a good starting point is ngReact http://davidchang.github.io/ngReact/index.html


#9

Thank you mate, I’ll try it out.


#10

Can we make it reverse? Like instead of scroll down, I would like to call function when user scroll up to the page.?


#11

I have the same issue here.


#12

Any news to this topic?

I’m also interested in a scrollTop feature for infiniteScrolling.


#13

Any news here? Having such a hard time with infinite scrolling lists with the latest beta. keeps crashing my ios 4. begining to dread ever using ionic in the first place.


#14

i stay with beta13. Tried before 2 weeks beta14 and infinite scroll seems too slow. Even on iOS i did feel. Wait for native scroll. Today I try to integrate with native view at all for some views.


#15

Somebody tried to use ngReact like @littleiffel pointed above?


#16

What I did to get a reverse (top) infinite scroll was hack the ion-refresh.

TEMPLATE

 <ion-refresher on-refresh="loadMore()" pulling-text="Load more" ng-if="!infiniteScrollPrevent"></ion-refresher>

CONTROLLER

  $scope.loadMore = function() {
if (typeof $scope.collection !== 'undefined') {
  var scrollBefore = document.getElementById('content').scrollHeight;
  // hide the finite scroll if too many and load the remaining
  if ($scope.collection.length + $scope.infiniteScrollLoadAmount > Messages.getLength()) {
    $scope.infiniteScrollPrevent = true;
    $scope.collection = Messages.getSectionReverse($scope.collection.length, Messages.getLength() - $scope.collection.length).concat($scope.collection);
  } else {
    // update data with new section
    $scope.collection = Messages.getSectionReverse($scope.collection.length, $scope.infiniteScrollLoadAmount).concat($scope.collection);
  }

  // hide loading icon
  $scope.$broadcast('scroll.refreshComplete');

  // scroll to the previous spot
  $timeout(function () {
    var scrollAfter = document.getElementById('content').scrollHeight;
    $ionicScrollDelegate.scrollTo(0, scrollAfter-scrollBefore, false);
  }, 200);
}

}


#17

Here’s another solution that creates a new directive that’s really just a wrapper for ion-refresher. They also posted a working plunkr.


#18

Starting from this: http://kirbysayshi.com/2013/08/19/maintaining-scroll-position-knockoutjs-list.html and from the original ionic-infinite-scroll I made this: http://codepen.io/assistenza_twell/pen/grKjRJ

It’s still in development but is good…

Someone knows how to do not show the scrolling? Is fast, but is not good to see.

Thanks.