Scroll View: How can I track which rows are visible?


#1

I would like to track which rows in a scroll view are visible as the user scrolls. This will allow me to update a chart that appears above the scroll view. See attached image for use case.

I created a directive that binds to the scroll event. I can determine the height of the scroll view and I can determine the scroll position y-offset using $ionicScrollDelegate.getScrollPosition().top.

  1. Can someone advise me on how to determine the height of an ion-list > ion-item from within my scrollWatch directive?
  2. Am I approaching this correctly? Is there a better way to calculate which rows are visible?


#2

I am using this angular plugin ( Angular in-view ) for a similar purpose and it works perfectly!

Hope it helps.


#3

Thanks @panospcm. That will definitely do the trick if I can’t figure out how to do it otherwise.


#4

I got pretty close. document.querySelector('div.collection-repeat-container') seemed to get the correct parent DOM object, but I couldn’t access any of its “ion-item” children for some reason. The codepen works pretty well with the hard-coded height of 55.

.controller('HomeCtrl', function($scope) {
  // Track visible rows
  $scope.row = {
    first: 0,
    last: 0
  } 
}) 

.directive('scrollWatch', function($ionicScrollDelegate) {
  return {
    restrict: 'A',
    link: function (scope, element) {
            
      var scrollViewHeight = element[0].clientHeight;
      var rowHeight = 55; //TODO: Calculate. All rows will be equal height
      var rowsInView = scrollViewHeight / rowHeight;
      
      // TODO: How can i get row height?? Currently hardcoded to 55.
      // collectionContainer.firstChild is null somehow.
      var collectionContainer = document.querySelector('div.collection-repeat-container');
      console.log(collectionContainer.firstChild);

      function update(shouldDigest) {
        var top = $ionicScrollDelegate.getScrollPosition().top;
        var first = top / rowHeight;
        var last = first + rowsInView;

        scope.row.first = Math.floor(first);
        scope.row.last = Math.floor(last);
        if (shouldDigest) scope.$apply();
      }
      
      // update on scroll
      element.bind('scroll', function() {
        update(true);
      });
      // update on load
      update(false);
    }
  };
});