1

I'm using ngInfiniteScroll ng-module for my pagination. When i scroll down the page i'm appending 20 records to my data table. By doing that, i'm actually running a http request each time ("not good for performance).

I've been doing some research and came across adding a LimitTo with the ngInfiniteScroll. Not sure how to implement this. Could someone please give me any suggestions.

   <table infinite-scroll='tF.loadMore()' infinite-scroll-disabled='tF.isBusy' infinite-scroll-distance='3' class="responsive">
            <thead>
                <tr>
                    <th>FIRST NAME</th>
                    <th>LAST NAME</th>
                    <th>USERNAME</th>
                    <th>EMAIL</th>
                    <th>CREATED DATE</th>
                    <th>STATUS</th>
                    <th>IS ONLINE</th>
                    <th>ACTIONS</th>
                </tr>
            </thead>
            <tbody>
                <tr ng-repeat="item in tF.items | filter:searchFilter">
                    <td>{{item.FirstName}}</td>
                    <td>{{item.LastName}}</td>
                    <td>{{item.Username}}</td>
                    <td>{{item.Email}}</td>
                    <td>{{item.CreatedDate | date:'medium'}}</td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </tbody>
            <tfoot ng-show='tF.isBusy'>
                <tr>
                    <td colspan="9"><spinner show="tF.isBusy" /><span class="bold">{{tF.status}}</span> </td>
                </tr>
            </tfoot>
        </table>

/**** CONTROLLER.JS *****/

    var vm = this;
    var page = 0;
    vm.items = [];
    vm.isBusy = false;

    vm.loadMore = function ()
    {
        if(vm.isBusy) return;
        vm.isBusy = true;

        userService.GetAllRecords(page)
        .success(function (data)
        {
            var results = data;

            for (var i = 0; i < results.length; i++)
            {
                vm.items.push(results[i]);
            }

            page++;
            vm.isBusy = false;

        }.bind(vm))
        .error(function (error)
        {
            vm.status = 'Error retrieving data! ' + error.message;
        })
        .finally(function ()
        {
            vm.isBusy = false;
        });
    }
Erkan Demir
  • 775
  • 1
  • 7
  • 24
  • If you don't want to load new data everytime, then why use infinite scroll? What is your goal? – devqon May 29 '15 at 06:46
  • I do want to load new data every time. However i was wondering if there is an alternative way of loading the data instead of calling a http request everytime i scroll. e.g. load all the data once when use the limitTo filter to append the data – Erkan Demir May 29 '15 at 06:51
  • Yeah you can load all data at once, and append pieces while scrolling. But I really think a http request is what you would want with an infinite scroll – devqon May 29 '15 at 06:53
  • Couldn't i just call a http request once, and load all the data to an array. then use limitTo filter to append e.g. + 20 records each time i scroll ? – Erkan Demir May 29 '15 at 06:55

2 Answers2

1

You could load all data once, and append pieces while scrolling:

var vm = this;
var page = 0;
vm.currentItems = [];
var allData = [],
    step = 10;

vm.loadData = function ()
{
    userService.GetAllRecords(page)
    .success(function (data)
    {
        allData = data;
        vm.loadMore(); // Set first 10 items
    })
    .error(function (error)
    {
        vm.status = 'Error retrieving data! ' + error.message;
    });
}

vm.loadMore = function () {
    // Add more items to the currentItems
    vm.currentItems = vm.currentItems.concat(allItems.slice(page*step, step));
    page++;
}

vm.loadData();

But it depends on what you are trying to achieve why you would want this. If most of the time the users only need to see the first 10 items, then I would recommend to do a http request each time you want to load more. If a user usually scrolls through all the items, then loading all data at once may be what you want.

devqon
  • 12,918
  • 2
  • 28
  • 43
  • The reason why i want to do the http request once is due to i have search filter, and you can only filter by the available records showing not the entire data list. @devqon – Erkan Demir Jun 30 '15 at 05:14
  • Yeah then you can totally do that, but if you have thousands of records that would not be a good idea. You could always do server side filtering with search – devqon Jun 30 '15 at 07:19
  • I will probably end up having a million records. What would be a better solution ? @devqon – Erkan Demir Jul 01 '15 at 00:36
0

I've used this module myself in a few applications and this is how you would restrict the call to only running once until your data has been returned.

js code

vm.isBusy = false;

vm.loadMore = function() {
    vm.isBusy = true;

    userService.GetAllRecords(page).success(function(data) {
        var results = data;

        for (var i = 0; i < results.length; i++) {
            vm.items.push(results[i]);
        }

        page++;
        vm.isBusy = false;
    });
}

template code

<div infinite-scroll="loadMore()" infinite-scroll-distance="0" infinite-scroll-disabled="isBusy"></div>

-

This is the code i wrote the last time i used this module.

<div infinite-scroll="loadMoreArticles()" infinite-scroll-distance="0" infinite-scroll-disabled="loadingArticles"></div>

$scope.loadingArticles = false;

$scope.loadMoreArticles = function() {
    $scope.loadingArticles = true;

    return articlesFactory.getArticles($stateParams.feedType || 'feed', $stateParams.feed, lastArticle.id).then(function(data) {
        $scope.articles = _.union($scope.articles, data);
        if (data.length > 0) {
            $scope.loadingArticles = false;
        }
    });
};
Joshua Kelly
  • 728
  • 5
  • 11