KingStakh KingStakh - 5 months ago 117
AngularJS Question

JSON Response with infinite scroll

I have troubles with infinite scroll function.
Every time when I scroll down loadMore function called twice and every time load 2 page instead of 1 page.
In log I see loading 2 and 3 page:

loadMore 2
loadMore 3


Then load 4 and 5 page:

loadMore 4
loadMore 5


This my controller:

.controller('PostsCtrl', function( $scope, $http, DataLoader, $timeout, $ionicSlideBoxDelegate, $rootScope, $log ) {

var postsApi = $rootScope.url + 'posts';

$scope.moreItems = false;

$scope.loadPosts = function() {

// Get all of our posts
DataLoader.get( postsApi ).then(function(response) {

$scope.posts = response.data;

$scope.moreItems = true;

$log.log(postsApi, response.data);

}, function(response) {
$log.log(postsApi, response.data);
});

}

// Load posts on page load
$scope.loadPosts();

paged = 2;

// Load more (infinite scroll)
$scope.loadMore = function() {

if( !$scope.moreItems ) {
return;
}

var pg = paged++;

$log.log('loadMore ' + pg );

$timeout(function() {

DataLoader.get( postsApi + '?page=' + pg ).then(function(response) {

angular.forEach( response.data, function( value, key ) {
$scope.posts.push(value);
});

if( response.data.length <= 0 ) {
$scope.moreItems = false;
}
}, function(response) {
$scope.moreItems = false;
$log.error(response);
});

$scope.$broadcast('scroll.infiniteScrollComplete');
$scope.$broadcast('scroll.resize');

}, 1000);

}

$scope.moreDataExists = function() {
return $scope.moreItems;
}

// Pull to refresh
$scope.doRefresh = function() {

$timeout( function() {

$scope.loadPosts();

//Stop the ion-refresher from spinning
$scope.$broadcast('scroll.refreshComplete');

}, 1000);

};

})


How call loadMore one time?
This my template:

<ion-view view-title="Posts">
<ion-content>
<ion-refresher on-refresh="doRefresh()"></ion-refresher>
<ion-list>
<ion-item class="item-icon-right" ng-repeat="post in posts track by $index" href="#/app/posts/{{post.id}}" track>
<!-- <img ng-if="post.featured_image" ng-src="{{post._embedded['http://v2.wp-api.org/attachment'][0][$index].source_url}}" class="alignleft" /> -->
<h2 ng-bind-html="post.title.rendered"></h2>
<p ng-if="post.excerpt.rendered" ng-bind-html="post.excerpt.rendered"></p>
<i class="icon ion-chevron-right icon-accessory"></i>
</ion-item>
</ion-list>

<ion-infinite-scroll
ng-if="moreDataExists()"
on-infinite="loadMore()"
distance="1%"
immediate-check="false">
</ion-infinite-scroll>

</ion-content>
</ion-view>

Answer

You should broadcast the infiniteScrollComplete event inside the callback of DataLoader.get

What's happenning is the Get method is assincronous, so your data is being added to the list after the event is fired.

Try changing your code to this, and it should work.

DataLoader.get( postsApi + '?page=' + pg ).then(function(response) {

    angular.forEach( response.data, function( value, key ) {
      $scope.posts.push(value);
    });

    if( response.data.length <= 0 ) {
      $scope.moreItems = false;
    }

    // Place here
    $scope.$broadcast('scroll.infiniteScrollComplete');

  }, function(response) {
    $scope.moreItems = false;
    $log.error(response);
  });