Question

I have a list of items displayed with ng-repeat at my web app, to get the items I call a service (rest) with pagination enabled, at the moment I am able to display just the first page. Now I need to implement some mechanics to make futher calls to load page 2, 3 ... as soon as the user scroll to the end of the current page.

For example, if pages are 20 items long and I am at the first page and I scroll down till item number 20, app will call page 2 and the items array will be expanded with the new items.

To top it all, it would be also very nice if there is a "pre-load" area which is not yet visible but elements are already there, ready to be shown to provide a smooth navigation, similar to "PageAdaptar" in Android.

What the best approach to do this in angular-js?

Thank you !

Was it helpful?

Solution

That is what finally I've done

I am using jquery to detect when I am at 300 px or less close to the bottom, in that case I call onScrollBottomEvent() from my controller, notice that this function may be called n times during scroll if user is inside of the 300px margin and he keeps going down.

<script type="text/javascript">
var lastScrollTop = 0;
$(window).scroll(function(event) {

    scrolled = $(window).scrollTop() + $(window).height();
    scrollMax = $('#container').height() + 50;

    if(scrolled >= (scrollMax-300)) {
        angular.element('#container').scope().onScrollBottomEvent();
    }
});
</script>

then onScrollBottomEvent() calls loadNextPage() using apply() [important!] Inside loadNextPage I set the flag onLoadMoreRequested to true, because I just need to call just once in order to load the next page instead of calling on every pixel scroll

$scope.onScrollBottomEvent = function(){
    $log.log("onScrollBottomEvent()");
    $scope.$apply(loadNextPage);
}

function loadNextPage(){
    $log.log("loadNextPage()");
    // execute only if there is other request on fly
    if (!$scope.onLoadMoreRequested){
        $scope.onLoadMoreRequested = true;
        $scope.appendNewItems($scope.search.data, $scope.lastLoadedPage + 1);
    }
}

finally I call the method to invoke the service

$scope.appendNewItems = function(search, page){
    $log.log("Loading items request for page " + page);
    $scope.footerProgressVisible = true;
    if ($scope.lastSearch != $scope.search.data){
        page = 0; // if search has changed, set page to zero
    }
    srvItems.getItems(search, function(result, page){
        $scope.footerProgressVisible = false;
        if (result!=null){
            $scope.items.push.apply($scope.items, result);
            $scope.lastLoadedPage = page;
            $scope.onLoadMoreRequested = false;
            $scope.lastSearch = $scope.search.data;
        }
    }, 
    $scope.currentCategoryId,
    page);
};

The key line is

 $scope.items.push.apply($scope.items, result);

which will expand my ng-repeat automatically

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top