werdnamai
werdnamai

Reputation: 21

Maintain scroll position after adding items to array in ng-repeat

Have list of messages displayed via ng-repeat, when user scrolls to top older messages are loaded via ion refresher. Desired behavior is for older messages to be added above the current messages, and the scroll position of current messages to be maintained.

HTML

<ion-content id="messageScroller" delegate-handle="userMessageScroll">

  <ion-refresher pulling-icon="ion-ios-arrow-thin-down" refreshing-text="loading messages" on-refresh="moreMessages()">
  </ion-refresher>

  <div ng-repeat="message in convo.messages">
    {{message.text}}
  </div>
</ion-content>

JS

$scope.moreMessages = function() {
  $scope.convo.messages = olderMessages().concat($scope.convo.messages)
}

Problem is when more messages is called, the ion-content scrolls to the top (stays at the top?).

How to set scroll position so loading older messages just makes the older messages accessable by scrolling up? Like it does in iMessage, or other chat apps?

Upvotes: 2

Views: 2669

Answers (2)

lyjackal
lyjackal

Reputation: 3984

I needed to do the same thing in my app and made a directive, just place the <load-more-at-top> directive before an <ion-list> within an <ion-content>

Here's a working plunker

myApp.directive('loadMoreAtTop', function($timeout) {
  return {
    restrict: 'E',
    scope: { onScroll: '&onScroll' },
    require: '^$ionicScroll',
    template: function() {
        return '<ion-refresher pulling-text="More..." on-refresh="growBounds()"></ion-refresher>';
    },
    link: function($scope, $element, attrs, scrollCtrl) {
      var scroller = scrollCtrl.$element[0];
      var lastHeight, 
          loading = false;
      $scope.growBounds = function growBounds() {
          loading = true;
          lastHeight = scroller.scrollHeight;
          console.log('lastHeight', lastHeight);
          $scope.onScroll();
      }

      function resetScrollPosition() {
          var height = scroller.scrollHeight;
          var difference = height - lastHeight;
          console.log('difference', difference, 'height', height, 'lastHeight', lastHeight);
          // reset the scroll based on previous height
          scrollCtrl.scrollTo(scrollCtrl.getScrollPosition().left, difference, true);
      }

      function finishGrowBounds() {
        if(loading) {
          $timeout(function() {
              loading = false;
              resetScrollPosition();
              $scope.$broadcast('scroll.refreshComplete');
          }, 0);
        }
      }

      $scope.$parent.$on('scroll.loaded', finishGrowBounds)
    }
  };
});

Upvotes: 0

lyjackal
lyjackal

Reputation: 3984

look into $ionicScrollDelegate. You can set and get the scroll position

Upvotes: 2

Related Questions