krishnair1123
krishnair1123

Reputation: 71

Pagination of nested objects in angular js

I am starting out with angular and I have a nested object which i would like to paginate. The items to be paginated are some of the 'attributes' in the given object. The queuelist object is nested with array within array. Any help would be appreciated. The plunker link for non-paginated data is:

https://plnkr.co/edit/zgo0msd6y5ba6DJ6qGlc?p=preview

app.js:

var app = angular.module("myApp",[])
                 .controller("mycontroller",['$scope',function($scope){

  $scope.queuelist = [
  {
    "name": "ONE",
    "QueueList": [
      {
        "id": 1,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:64"
      },
      {
        "id": 2,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:65"
      },
      {
        "id": 3,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:66"
      }
    ],
    "$$hashKey": "object:59"
  },
  {
    "name": "TWO",
    "QueueList": [
      {
        "id": 4,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:72"
      },
      {
        "id": 5,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:73"
      },
      {
        "id": 6,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:74"
      },
      {
        "id": 7,
        "attributes": {
          "a": 1,
          "b": "2017-07-25T12:57:06Z",
          "c": 1500967626000,
          "d": "asdasd",
          "e": "aasdasdasd",
          "f": 0
        },
        "$$hashKey": "object:75"
      }
    ],
    "$$hashKey": "object:60"
  }
];


  $scope.objects = [];


   /*                  
  for(i=0;i<$scope.data.length;i++){
      $scope.data2.push($scope.data[i].QueueList);
  };
   */

    for(i=0;i<$scope.queuelist.length;i++){
      for(j=0;j<$scope.queuelist[i].QueueList.length;j++){
          $scope.objects.push($scope.queuelist[i].QueueList[j].attributes);
      };
    };              
   }])

and index.html:

<!DOCTYPE html>
<html ng-app="myApp">
    <head>
        <script type= "text/javascript" src= "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
        <script type= "text/javascript" src= "app.js"></script>
        <style>
            table, td, th {    
            border: 1px solid #ddd;
            text-align: left;
            }

            table {
            border-collapse: collapse;
            width: 100%;
            }

            th, td {
            padding: 15px;
            }
        </style>
    </head>
    <body>
        <div ng-controller="mycontroller">

            <div ng-repeat="queueJob in queuelist">
                {{queueJob.name}}
                <table>
                    <thead>
                        <tr>
                            <th><b>a</b></th>
                            <th><b>b</b></th>
                            <th><b>c</b></th>
                            <th><b>e</b></th>
                            <th><b>f</b></th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr ng-repeat="queue in queueJob.QueueList">
                            <td>{{queue.attributes.a}}</td>
                            <td>{{queue.attributes.b}}</td>
                            <td>{{queue.attributes.c}}</td>
                            <td>{{queue.attributes.e}}</td>
                            <td>{{queue.attributes.f}}</td>
                        </tr>
                        <br/><br/>
                    </tbody>
                </table>
                <br/><br/>
                <br/><br/>
            </div>

        </div>
    </body>
</html>

Upvotes: 4

Views: 1225

Answers (1)

Matthew Cawley
Matthew Cawley

Reputation: 2818

You can do this using a combination of:

  • A custom filter (to determine how many records to skip), and...
  • The built in limitTo filter (to limit the number of records to the desired page size)

1) First create the custom filter.

app.filter("startFrom", function thisFilter() {
  return function(input, index) {
    return input.slice(parseInt(index));
  };
});

The filter takes in an index which it goes on to use in the Array.prototype.slice() method. The slice() method slices the array at the given index and returns a new array containing all remaining objects. The filter returns the new array.

2) Use the custom filter and built-in limitTo filter in the ng-repeat directive.

<tr ng-repeat="queue in queueJob.QueueList | startFrom: queueJob.pageIndex | limitTo: 1">

Here we use the newly created startFrom custom filter passing it the queueJob.pageIndex property as the filter's index parameter. We pass the results of the startFrom filter onto the limitTo filter which reduces the number of records to 1.

Note: We have to use the pageIndex property on the queueJob itteration variable because this ng-repeat is contained within another ng-repeat and so a $scope.pageIndex variable would have been conflicted and subsequently overwritten.

3) Create next and previous buttons

<tr>
  <td colspan="5">
    <button class="btn" 
      ng-click="onPrevClicked(queueJob)"
      ng-disabled="isFirst(queueJob)">
      <span class="fa fa-chevron-left"></span>
      Prev
    </button>
    <button class="btn" 
      ng-click="onNextClicked(queueJob)"
      ng-disabled="isLast(queueJob)">
      Next
      <span class="fa fa-chevron-right"></span>
    </button>
    Page {{ queueJob.pageIndex + 1 }}
  </td>
</tr>

Here we use ng-click directives to invoke controller functions that increment/decrement the queueJob object's pageIndex property. We also use ng-disabled directives to prevent navigating next/previous if the user is on the first/last record.

4) Create the bindable functions in the controller

$scope.onPrevClicked = onPrevClicked;
$scope.onNextClicked = onNextClicked;
$scope.isFirst = isFirst;
$scope.isLast = isLast;

function onPrevClicked(obj) {
  if (!isFirst(obj)) obj.pageIndex--;
}

function onNextClicked(obj) {
  if (!isLast(obj)) obj.pageIndex++;
}

function isFirst(obj) {
  return obj.pageIndex === 0;
}

function isLast(obj) {
  return obj.pageIndex + 1 === obj.QueueList.length;
}

5) Initialise the pageIndex properties upfront

$scope.queuelist.forEach(function(obj) {
  obj.pageIndex = 0;
});

This initialised the pageIndex as a number that can be incremented and subsequently decremented.

Demo

CodePen: Using a custom filter to do pagination

Upvotes: 3

Related Questions