1

I'm using spring framework for backend and AngularJS. I need to use server-side and client-side pagination for one table, so I will pass page number and page size to rest service. Now I need to do the following scenario:

If I have 20000 records in the database:

  1. Get first 2500 records from the database then paginate through them.

  2. After paginate through the first 2500 records, get next 2500 records (from 2501 to 5000) and so on until finish all records in the database.

Can I do that with Angular datatable or any Angular tables?

Mika Sundland
  • 18,120
  • 16
  • 38
  • 50
Ali-Alrabi
  • 1,515
  • 6
  • 27
  • 60
  • 1
    You could use simple table and then add paginate directive to having pagination https://angular-ui.github.io/bootstrap/#/pagination on your table .. or if you think of grid with having pagination then you could go for Angular-ui's `ui-grid` http://ui-grid.info/ – Pankaj Parkar Nov 29 '15 at 10:04
  • Thank for you reply, Can I do it by angular datatabe http://l-lin.github.io/angular-datatables/ and how should it work with ui-grid? – Ali-Alrabi Nov 29 '15 at 10:10

1 Answers1

0

We had exactly the same requirement what you have described. We searched on web we didn't get the solution. Finally we researched and came up with a solution. Hope it will help others who are looking for solution.

We are using Angular ui grid. In angular ui.grid you can either use default client side pagination or you can implement external(or server side) pagination.

But, In your requirement, you need combination of client and server side pagination, which is flexible and very much required when you have huge data (number of records in Lacks).

If you don't know how to use server side pagination then look at How to use Angular UI-Grid with Server Side Paging question. You can have a look at working server side pagination implementation http://plnkr.co/edit/UttxPkXG8fYQDX85fnyZ?p=preview.

I am modifying this implementation in order to achieve combination of client side and server side pagination.

var useHybridPagination = true;
var paginationPageSize = 25;
var serverPaginationPageSize = 2500;    
var serverPaginationOffset = 0;
var serverPaginationGridData = {};

var clientPaginationOptions  = {
        pageNumber: 1,
        pageSize: paginationPageSize,           
      };

var serverPaginationOptions = {
        pageNumber: 1,
        pageSize: serverPaginationPageSize,         
      };    

var paginationRowRange = {}
paginationRowRange.startRowIndex = 1;
paginationRowRange.endRowIndex = paginationPageSize;

var serverPaginationRowRange = {}
serverPaginationRowRange.startRowIndex = 1;
serverPaginationRowRange.endRowIndex = serverPaginationPageSize;   

I am going to use Server side pagination logic to pull every 2,500 records. And to navigate across pages at client side (2500 records), will going to make little modification. if the new page sought by user exists in 2500 records at client side then slice the number of records as indicated by serverPaginationOptions.pageSize and load the grid. Or else fetch next 2500 records & re-evaluate row indexes.

$scope.clientPaginationOptions  = clientPaginationOptions ;
$scope.serverPaginationOptions = serverPaginationOptions;
$scope.paginationRowRange = paginationRowRange;
$scope.serverPaginationRowRange = serverPaginationRowRange;
$scope.serverPaginationOffset = serverPaginationOffset;
$scope.serverPaginationGridData = serverPaginationGridData;

$scope.gridOptions = {
    paginationPageSizes: [25, 50, 75],
    paginationPageSize: $scope.clientPaginationOptions .pageSize,
    useExternalPagination: true,        
    columnDefs: [
      { name: 'name' },
      { name: 'gender', enableSorting: false },
      { name: 'company', enableSorting: false }
    ],
    onRegisterApi: function(gridApi) {
      $scope.gridApi = gridApi;

      gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
        $scope.clientPaginationOptions .pageNumber = newPage;
        $scope.clientPaginationOptions .pageSize = pageSize;

        let startRowIndex = (($scope.clientPaginationOptions .pageNumber - 1) * $scope.clientPaginationOptions .pageSize) + 1;
        let endRowIndex =  (startRowIndex - 1 ) + clientPaginationOptions .pageSize;            

        if(endRowIndex > $scope.serverPaginationRowRange.endRowIndex || startRowIndex < $scope.serverPaginationRowRange.startRowIndex){             

            $scope.serverPaginationOptions.pageNumber = parseInt(($scope.clientPaginationOptions .pageNumber * pageSize)/$scope.serverPaginationOptions.pageSize) + 1;

            let serverStartRowIndex = (($scope.serverPaginationOptions.pageNumber - 1) * $scope.serverPaginationOptions.pageSize) + 1;
            let serverEndRowIndex =  (serverStartRowIndex - 1 ) + $scope.serverPaginationOptions.pageSize;                  

            let paginationRowRangeTmp = {}
            paginationRowRangeTmp.startRowIndex = serverStartRowIndex;
            paginationRowRangeTmp.endRowIndex = serverEndRowIndex;    
            $scope.serverPaginationRowRange = paginationRowRangeTmp;                

            $scope.serverPaginationOffset = serverStartRowIndex - 1;
        }

        startRowIndex = startRowIndex - $scope.serverPaginationOffset;
        endRowIndex = endRowIndex - $scope.serverPaginationOffset;          

        let paginationRowRangeTmp = {}
        paginationRowRangeTmp.startRowIndex = startRowIndex;
        paginationRowRangeTmp.endRowIndex = endRowIndex;    
        $scope.paginationRowRange = paginationRowRangeTmp; 

        getPage();
      });
    }
};
getPage();

var getPage = function() {

    if(useHybridPagination && !_.isEmpty($scope.serverPaginationGridData)){
        var currentPageData = getcurrentPageData();
        $timeout(function() {
            $scope.gridOptions.data = datatoLoadGrid;
           }, 1);
    }
    else{
        var url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
        $http.get(url,$scope.serverPaginationRowRange)
            .then(function (returnData) {
                $scope.gridOptions.totalItems = returnData.data.totalPaginationRecords;
                let datatoLoadGrid = returnData.data.gridData;

                if(useHybridPagination){
                    $scope.serverPaginationGridData = datatoLoadGrid;
                    datatoLoadGrid = getcurrentPageData();
                }
                $scope.gridOptions.data = datatoLoadGrid;
            });
    }
};  

var getcurrentPageData = function(){
    var gridData = [];

    var tmpGridrecords = $scope.serverPaginationGridData;
    if(!_.isEmpty(tmpGridrecords) && tmpGridrecords.length > 0)
        gridData = tmpGridrecords.slice($scope.paginationRowRange.startRowIndex-1, $scope.gridOptions.endRowIndex);

    return gridData;
};  

As you can see, the web service (or API) returns data object with 2 properties - totalPaginationRecords & gridData. totalPaginationRecords is total number of records possible i.e. in our case it is 20,000. gridData is the grid data to be loaded (Page size 2500).

All corner conditions are handled. Hope it helps. All suggestions/corrections to improve this solution are welcome.

Naveenk
  • 78
  • 7