Tutorial: ng-table with infinite scroll

I’ve already showed in this blog how to create a basic datatable with ng-table, for those who didn’t see it yet, just click on the link. This tutorial will just be a complement to the previous one, the difference is that instead of using pagination I’m going to use infinite scroll, and don’t worry, I’ll also keep the sorting and filtering features.

So before we start let’s just put the links to every script we need, your index.html should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html ng-app="ngTableTutorial">
    <head>
        <title>ng-table with infinite scroll</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
        <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
        <script src="http://netdna.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js" type="text/javascript"></script>
        <script src="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.js"></script>
        <script src="https://raw.githubusercontent.com/BinaryMuse/ngInfiniteScroll/1.0.0/build/ng-infinite-scroll.min.js"></script>
        <link rel="stylesheet" href="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.css">
        <link href="http://netdna.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" media="screen">
 
        <script src="app/resources/js/app.js" type="text/javascript"></script>
        <link href="app/resources/css/style.css" rel="stylesheet" type="text/css"/>
    </head>
    <body style="padding: 50px">
        <div ng-controller="tableController">
        </div>
    </body>
</html>

As you can see I just put the links to: JQuery, Angular, bootstrap, ng-table and ngInfiniteScroll. There’s also the app.js and style.css, which I created to put my code on them.

Note that the body is still empty for now, let’s leave it like this and open our app.js, the first thing we need to do is to create our angular module and controller, just copy the following code to your app.js:

1
2
3
4
angular.module('ngTableTutorial', ['ngTable','infinite-scroll'])
        .controller('tableController', function ($scope, $filter, ngTableParams) {
        }
);

Don’t forget to declare the ngTable and infinite-scroll as dependencies, we’re going to use them later. This code is still very simple, I just created a module called ngTableTutorial, if you go back to the index.html code you’ll see that the ng-app=”ngTableTutorial” is already there in the html tag, and I also created a controller called tableController, again if go to the index.html there will be a div inside our body with the attribute ng-controller=”tableController”.

Now we need some data to be displayed to the table, I personally like mockaroo to generate random data, but feel free to generate it as you like, you’ll need about 1000 rows for this tutorial, after you generate it, just put it in a variable inside you controller, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$scope.users =
        [{
                "id": 1,
                "first_name": "Theresa",
                "last_name": "Morris",
                "email": "tmorris0@myspace.com",
                "country": "Indonesia",
                "ip_address": "143.220.154.199"
            }, {
                "id": 2,
                "first_name": "Steve",
                "last_name": "Gray",
                "email": "sgray1@nytimes.com",
                "country": "Norway",
                "ip_address": "163.199.165.94"
            }
           .
           .
           .
            {
                "id": 1000,
                "first_name": "Gloria",
                "last_name": "West",
                "email": "gwest2@go.com",
                "country": "China",
                "ip_address": "16.171.225.220"
            }
];

Now that we have the data we’re ready to create our table, copy the table bellow inside your div with the ng-controller attribute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<table infinite-scroll="getMoreData()" ng-table="tableParams" show-filter="true" class="table table-striped">
    <tr ng-repeat="user in data">
        <td data-title="'Id'" sortable="'id'">
            {{user.id}}
        </td>
        <td data-title="'First Name'" sortable="'first_name'" filter="{ 'first_name': 'text' }">
            {{user.first_name}}
        </td>
        <td data-title="'Last Name'" sortable="'last_name'" filter="{ 'last_name': 'text' }">
            {{user.last_name}}
        </td>    
        <td data-title="'e-mail'" sortable="'email'">
            {{user.email}}
        </td>    
        <td data-title="'Country'" sortable="'country'">
            {{user.country}}
        </td>    
        <td data-title="'IP'" sortable="'ip_address'">
            {{user.ip_address}}
        </td>    
    </tr>
</table>

Each column is displaying one attribute of our JSON, I put the attribute sortable and filter in some of them to add the sorting and filtering features to the datatable (to show the filter you also have to put show-filter=”true” in your table). But what is important here is the attributes ng-table=”tableParams” and infinite-scroll=”getMoreData()” from the table, the first is binding the table to the tableParams variable in our controller (I’m still going to create this variable), and the second attribute receives the method that will be called when the user reaches the bottom of the page, that’s the method that will make our infinite scroll work.

Now the only thing left for us to do is to create our tableParams and implement the getMoreData() method, copy the following code bellow our JSON in your controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$scope.tableParams = new ngTableParams({
    page: 1,
    count: $scope.users.length
}, {
    counts: [],
    total: 1,
    getData: function ($defer, params) {
        $scope.data = params.sorting() ? $filter('orderBy')($scope.users, params.orderBy()) : $scope.users;
        $scope.data = params.filter() ? $filter('filter')($scope.data, params.filter()) : $scope.data;
        $scope.data = $scope.data.slice(0, 20);
        $defer.resolve($scope.data);
    }
});
 
$scope.getMoreData = function () {
    $scope.data = $scope.users.slice(0, $scope.data.length + 20);
}

In this code we are instantiating the ngTableParams, the fist object it receives as a parameter is just defining that the current page is 1 and setting the row count, but what really matters here is the function getData, it will be called on the table initialization and also every time we sort or filter it, the lines 8 and 9 contains the logic to sort and filter the data, note that in line 10 I’m getting only the first 20 rows of our data, I’m doing this because every time this method is called, or the user will be filtering the data or he’ll be sorting it, both actions require him to be on the top of the page, thus I don’t need to show more than 20 rows.

Ok, now we just need to load more rows when he reaches the bottom of the pages, take a look at line 16, it’s just adding 20 more rows to our data, note that I’m using 2 variables here: $scope.data and $scope.users. The last one contains our original data, we cannot modify it, otherwise we’ll lose the data, that’s why we need an auxiliary variable, just to manipulate the data.

That’s it, now if you run your project you should see the following result:

ngTable with Infinite scroll
ng-Table with infinite scroll

As you scroll down you’ll see that the scroll bar will get smaller and smaller.

Recommended for you

4 comments on “Tutorial: ng-table with infinite scroll

  1. Ruslan

    Could you make available to change scroll element. I mean, this directive working only if $window is scrolling, but not if another element in DOM.

Leave a Reply

Your email address will not be published. Required fields are marked *

Obs: Use the tag <pre lang="LANGUAGE"> to include code blocks to your comment.
Example: <pre lang="javascript"> console.log('Test'); </pre>