Comment faire la pagination dans AngularJS?
J'ai un ensemble de données d'environ 1000 éléments en mémoire et j'essaie de créer un pager pour cet ensemble de données, mais je ne suis pas sûr de la façon de le faire.
J'utilise une fonction de filtre personnalisée pour filtrer les résultats, et cela fonctionne bien, mais d'une manière ou d'une autre, j'ai besoin de sortir le nombre de pages.
Des indices?
21 réponses
Directive Bootstrap - Pagination de L'interface utilisateur angulaire
Consultez la directive de paginationde L'interface utilisateur Bootstrap . J'ai fini par l'utiliser plutôt que ce qui est posté ici car il a suffisamment de fonctionnalités pour mon utilisation actuelle et a une spécification de test approfondie pour l'accompagner.
Vue
<!-- table here -->
<pagination
ng-model="currentPage"
total-items="todos.length"
max-size="maxSize"
boundary-links="true">
</pagination>
<!-- items/page select here if you like -->
Contrôleur
todos.controller("TodoController", function($scope) {
$scope.filteredTodos = []
,$scope.currentPage = 1
,$scope.numPerPage = 10
,$scope.maxSize = 5;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:"todo "+i, done:false});
}
};
$scope.makeTodos();
$scope.$watch("currentPage + numPerPage", function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
});
});
J'ai fait un plunker de travail pour référence.
Héritage Version:
Vue
<!-- table here -->
<div data-pagination="" data-num-pages="numPages()"
data-current-page="currentPage" data-max-size="maxSize"
data-boundary-links="true"></div>
<!-- items/page select here if you like -->
Contrôleur
todos.controller("TodoController", function($scope) {
$scope.filteredTodos = []
,$scope.currentPage = 1
,$scope.numPerPage = 10
,$scope.maxSize = 5;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:"todo "+i, done:false});
}
};
$scope.makeTodos();
$scope.numPages = function () {
return Math.ceil($scope.todos.length / $scope.numPerPage);
};
$scope.$watch("currentPage + numPerPage", function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
});
});
J'ai fait un plunker de travail pour référence.
J'ai récemment implémenté la pagination pour le site construit avec Angular. Vous chan la caisse de la source: https://github.com/angular/builtwith.angularjs.org
J'éviterais d'utiliser un filtre pour séparer les pages. Vous devez diviser les éléments en pages dans le contrôleur.
J'ai dû implémenter la pagination plusieurs fois avec Angular, et c'était toujours un peu pénible pour quelque chose que je sentais pouvoir simplifier. J'ai utilisé certaines des idées présentées ici et ailleurs pour créer un module de pagination qui rend la pagination aussi simple que:
<ul>
<li dir-paginate="item in items | itemsPerPage: 10">{{ item }}</li>
</ul>
// then somewhere else on the page ....
<dir-pagination-controls></dir-pagination-controls>
C'est ça. Il a les caractéristiques suivantes:
- Aucun code personnalisé n'est nécessaire dans votre contrôleur pour lier la collection
items
aux liens de pagination. - Vous n'êtes pas obligé d'utiliser une table ou gridview - vous pouvez paginer tout ce que vous pouvez ng-répéter!
- délègue à
ng-repeat
, de sorte que vous pouvez utiliser n'importe quelle expression qui pourrait être valablement utilisée dans unng-repeat
, y compris le filtrage, l'ordre, etc. - Fonctionne entre les contrôleurs - la directive
pagination-controls
n'a pas besoin de savoir quoi que ce soit sur le contexte dans lequel la directivepaginate
est appelée.
Démo: http://plnkr.co/edit/Wtkv71LIqUR4OhzhgpqL?p=preview
Pour ceux qui recherchent un " plug and play" solution, je pense que vous trouverez cela utile.
Code
Le code est disponible ici sur GitHub et inclut un très bon ensemble de tests:
Https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
Si vous êtes intéressé j'ai aussi écrit une courte pièce avec un peu plus de perspicacité dans la conception du module: http://www.michaelbromley.co.uk/blog/108/paginate-almost-anything-in-angularjs/
Je viens de faire un JSFiddle qui montre pagination + search + order by sur chaque colonne en utilisant le code btford: http://jsfiddle.net/SAWsA/11/
J'ai mis à jour Scotty.NET " s plunkr http://plnkr.co/edit/FUeWwDu0XzO51lyLAEIA?p=preview afin qu'il utilise des versions plus récentes de angular, angular-ui et bootstrap.
Contrôleur
var todos = angular.module('todos', ['ui.bootstrap']);
todos.controller('TodoController', function($scope) {
$scope.filteredTodos = [];
$scope.itemsPerPage = 30;
$scope.currentPage = 4;
$scope.makeTodos = function() {
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:'todo '+i, done:false});
}
};
$scope.figureOutTodosToDisplay = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage);
var end = begin + $scope.itemsPerPage;
$scope.filteredTodos = $scope.todos.slice(begin, end);
};
$scope.makeTodos();
$scope.figureOutTodosToDisplay();
$scope.pageChanged = function() {
$scope.figureOutTodosToDisplay();
};
});
Composant D'interface utilisateur Bootstrap
<pagination boundary-links="true"
max-size="3"
items-per-page="itemsPerPage"
total-items="todos.length"
ng-model="currentPage"
ng-change="pageChanged()"></pagination>
C'est une solution javascript pure que j'ai enveloppée comme un service angulaire pour implémenter la logique de pagination comme dans les résultats de recherche google.
Démo de travail sur CodePen à http://codepen.io/cornflourblue/pen/KVeaQL/
Détails et explications à ce billet de blog
function PagerService() {
// service definition
var service = {};
service.GetPager = GetPager;
return service;
// service implementation
function GetPager(totalItems, currentPage, pageSize) {
// default to first page
currentPage = currentPage || 1;
// default page size is 10
pageSize = pageSize || 10;
// calculate total pages
var totalPages = Math.ceil(totalItems / pageSize);
var startPage, endPage;
if (totalPages <= 10) {
// less than 10 total pages so show all
startPage = 1;
endPage = totalPages;
} else {
// more than 10 total pages so calculate start and end pages
if (currentPage <= 6) {
startPage = 1;
endPage = 10;
} else if (currentPage + 4 >= totalPages) {
startPage = totalPages - 9;
endPage = totalPages;
} else {
startPage = currentPage - 5;
endPage = currentPage + 4;
}
}
// calculate start and end item indexes
var startIndex = (currentPage - 1) * pageSize;
var endIndex = startIndex + pageSize;
// create an array of pages to ng-repeat in the pager control
var pages = _.range(startPage, endPage + 1);
// return object with all pager properties required by the view
return {
totalItems: totalItems,
currentPage: currentPage,
pageSize: pageSize,
totalPages: totalPages,
startPage: startPage,
endPage: endPage,
startIndex: startIndex,
endIndex: endIndex,
pages: pages
};
}
}
J'ai extrait les bits pertinents ici. Il s'agit d'un pager tabulaire "sans fioritures", donc le tri ou le filtrage n'est pas inclus. N'hésitez pas à modifier / ajouter au besoin:
//your data source may be different. the following line is
//just for demonstration purposes only
var modelData = [{
text: 'Test1'
}, {
text: 'Test2'
}, {
text: 'Test3'
}];
(function(util) {
util.PAGE_SIZE = 10;
util.range = function(start, end) {
var rng = [];
if (!end) {
end = start;
start = 0;
}
for (var i = start; i < end; i++)
rng.push(i);
return rng;
};
util.Pager = function(data) {
var self = this,
_size = util.PAGE_SIZE;;
self.current = 0;
self.content = function(index) {
var start = index * self.size,
end = (index * self.size + self.size) > data.length ? data.length : (index * self.size + self.size);
return data.slice(start, end);
};
self.next = function() {
if (!self.canPage('Next')) return;
self.current++;
};
self.prev = function() {
if (!self.canPage('Prev')) return;
self.current--;
};
self.canPage = function(dir) {
if (dir === 'Next') return self.current < self.count - 1;
if (dir === 'Prev') return self.current > 0;
return false;
};
self.list = function() {
var start, end;
start = self.current < 5 ? 0 : self.current - 5;
end = self.count - self.current < 5 ? self.count : self.current + 5;
return Util.range(start, end);
};
Object.defineProperty(self, 'size', {
configurable: false,
enumerable: false,
get: function() {
return _size;
},
set: function(val) {
_size = val || _size;
}
});
Object.defineProperty(self, 'count', {
configurable: false,
enumerable: false,
get: function() {
return Math.ceil(data.length / self.size);
}
});
};
})(window.Util = window.Util || {});
(function(ns) {
ns.SampleController = function($scope, $window) {
$scope.ModelData = modelData;
//instantiate pager with array (i.e. our model)
$scope.pages = new $window.Util.Pager($scope.ModelData);
};
})(window.Controllers = window.Controllers || {});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<table ng-controller="Controllers.SampleController">
<thead>
<tr>
<th>
Col1
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in pages.content(pages.current)" title="{{item.text}}">
<td ng-bind-template="{{item.text}}"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<a href="#" ng-click="pages.prev()">«</a>
<a href="#" ng-repeat="n in pages.list()" ng-click="pages.current = n" style="margin: 0 2px;">{{n + 1}}</a>
<a href="#" ng-click="pages.next()">»</a>
</td>
</tr>
</tfoot>
</table>
L'adaptateur angulaire mobile jQuery dispose d'un filtre de pagination dont vous pouvez vous baser.
Voici un violon de démonstration qui l'utilise (ajouter plus de 5 éléments et il devient paginé): http://jsfiddle.net/tigbro/Du2DY/
Voici la source: https://github.com/tigbro/jquery-mobile-angular-adapter/blob/master/src/main/webapp/utils/paging.js
J'utilise cette bibliothèque de pagination 3ème partie et cela fonctionne bien. Il peut faire des sources de données locales/distantes et il est très configurable.
Https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination
<dir-pagination-controls
[max-size=""]
[direction-links=""]
[boundary-links=""]
[on-page-change=""]
[pagination-id=""]
[template-url=""]
[auto-hide=""]>
</dir-pagination-controls>
Ci-dessous solution assez simple.
<pagination
total-items="totalItems"
items-per-page= "itemsPerPage"
ng-model="currentPage"
class="pagination-sm">
</pagination>
<tr ng-repeat="country in countries.slice((currentPage -1) * itemsPerPage, currentPage * itemsPerPage) ">
Pour tous ceux qui trouvent difficile comme moi de créer un paginateur pour une table, je poste ceci. Donc, à votre avis:
<pagination total-items="total" items-per-page="itemPerPage" ng-model="currentPage" ng-change="pageChanged()"></pagination>
<!-- To specify your choice of items Per Pages-->
<div class="btn-group">
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Left'" data-ng-click="setItems(5)">5</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Middle'" data-ng-click="setItems(10)">10</label>
<label class="btn btn-primary" ng-model="radioModel" btn-radio="'Right'" data-ng-click="setItems(15)">15</label>
</div>
//And don't forget in your table:
<tr data-ng-repeat="p in profiles | offset: (currentPage-1)*itemPerPage | limitTo: itemPerPage" >
Dans votre angularJs:
var module = angular.module('myapp',['ui.bootstrap','dialogs']);
module.controller('myController',function($scope,$http){
$scope.total = $scope.mylist.length;
$scope.currentPage = 1;
$scope.itemPerPage = 2;
$scope.start = 0;
$scope.setItems = function(n){
$scope.itemPerPage = n;
};
// In case you can replace ($scope.currentPage - 1) * $scope.itemPerPage in <tr> by "start"
$scope.pageChanged = function() {
$scope.start = ($scope.currentPage - 1) * $scope.itemPerPage;
};
});
//and our filter
module.filter('offset', function() {
return function(input, start) {
start = parseInt(start, 10);
return input.slice(start);
};
});
Ng-pagination répétée
<div ng-app="myApp" ng-controller="MyCtrl">
<input ng-model="q" id="search" class="form-control" placeholder="Filter text">
<select ng-model="pageSize" id="pageSize" class="form-control">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
<ul>
<li ng-repeat="item in data | filter:q | startFrom:currentPage*pageSize | limitTo:pageSize">
{{item}}
</li>
</ul>
<button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
Previous
</button>
{{currentPage+1}}/{{numberOfPages()}}
<button ng-disabled="currentPage >= getData().length/pageSize - 1" ng- click="currentPage=currentPage+1">
Next
</button>
</div>
<script>
var app=angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', '$filter', function ($scope, $filter) {
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.data = [];
$scope.q = '';
$scope.getData = function () {
return $filter('filter')($scope.data, $scope.q)
}
$scope.numberOfPages=function(){
return Math.ceil($scope.getData().length/$scope.pageSize);
}
for (var i=0; i<65; i++) {
$scope.data.push("Item "+i);
}
}]);
app.filter('startFrom', function() {
return function(input, start) {
start = +start; //parse to int
return input.slice(start);
}
});
</script>
Depuis Angulaire 1.4, la limitTo
filtre accepte également un second argument optionnel begin
{{ limitTo_expression | limitTo : limite : début}}
Début (facultatif) chaîne|nombre
Index auquel commencer limitation. En tant qu'index négatif, begin indique un décalage par rapport à la fin de l'entrée. Par défaut à 0.
Vous N'avez donc pas besoin de créer une nouvelle directive , cet argument peut être utilisé pour définir le décalage du la pagination
ng-repeat="item in vm.items| limitTo: vm.itemsPerPage: (vm.currentPage-1)*vm.itemsPerPage"
Messages précédents recommandé essentiellement comment construire une pagination par vous-même. Si vous êtes comme moi, et préférez une directive finie, je viens de trouver un grand appelé ngTable . Il prend en charge le tri, le filtrage et la pagination.
C'est une solution très propre, tout ce dont vous avez besoin à votre avis:
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in $data">
<td data-title="'Name'" sortable="'name'">
{{user.name}}
</td>
<td data-title="'Age'" sortable="'age'">
{{user.age}}
</td>
</tr>
</table>
Et dans le contrôleur:
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
sorting: {
name: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
var start = (params.page() - 1) * params.count();
var end = params.page() * params.count();
$defer.resolve(orderedData.slice( start, end));
}
});
Lien vers GitHub: https://github.com/esvit/ng-table/
Voici mon exemple. Bouton sélectionné au milieu de la liste Contrôleur. config >>>
$scope.pagination = {total: null, pages: [], config: {count: 10, page: 1, size: 7}};
Logique de pagination:
/*
Pagination
*/
$scope.$watch('pagination.total', function (total) {
if(!total || total <= $scope.pagination.config.count) return;
_setPaginationPages(total);
});
function _setPaginationPages(total) {
var totalPages = Math.ceil(total / $scope.pagination.config.count);
var pages = [];
var start = $scope.pagination.config.page - Math.floor($scope.pagination.config.size/2);
var finish = null;
if((start + $scope.pagination.config.size - 1) > totalPages){
start = totalPages - $scope.pagination.config.size;
}
if(start <= 0) {
start = 1;
}
finish = start + $scope.pagination.config.size - 1;
if(finish > totalPages){
finish = totalPages;
}
for (var i = start; i <= finish; i++) {
pages.push(i);
}
$scope.pagination.pages = pages;
}
$scope.$watch("pagination.config.page", function(page){
_setPaginationPages($scope.pagination.total);
_getRespondents($scope.pagination.config);
});
Et ma vue sur bootstap
<ul ng-class="{hidden: pagination.total == 0}" class="pagination">
<li ng-click="pagination.config.page = pagination.config.page - 1"
ng-class="{disabled: pagination.config.page == 1}" ><a href="#">«</a></li>
<li ng-repeat="p in pagination.pages"
ng-click="pagination.config.page = p"
ng-class="{active: p == pagination.config.page}"><a href="#">{{p}}</a></li>
<li ng-click="pagination.config.page = pagination.config.page + 1"
ng-class="{disabled: pagination.config.page == pagination.pages.length}"><a href="#">»</a></li>
</ul >
, Il est utile
Est un excellent choix
Une directive pour faciliter la pagination de grands ensembles de données tout en exigeant le strict minimum d'informations de pagination réelles. Nous sommes très dépendants du serveur pour les résultats de "filtrage" dans ce schéma de pagination. L'idée centrale étant que nous voulons seulement tenir la "page" active des éléments-plutôt que de tenir la liste entière des éléments en mémoire et la pagination du côté client.
Ancienne question mais puisque je pense que mon approche est un peu différente et moins complexe, je vais partager cela et espérer que quelqu'un d'autre que moi le trouve utile.
Ce que j'ai trouvé être une solution facile et petite à la pagination est de combiner une directive avec un filtre qui utilise les mêmes variables de portée.
Pour implémenter cela, vous ajoutez le filtre sur le tableau et ajoutez le directiv comme ceci
<div class="row">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items | cust_pagination:p_Size:p_Step">
<td>{{item.Name}}</td>
<td>{{item.Price}}</td>
<td>{{item.Quantity}}</td>
</tr>
</tbody>
</table>
<div cust-pagination p-items="items" p-boundarylinks="true" p-size="p_Size" p-step="p_Step"></div>
</div>
P_Size et p_Step sont des variables de portée qui peuvent être personnalisées dans la portée sinon, la valeur par défaut de p_Size est 5 et p_Step est 1.
Lorsqu'une étape est un changement dans la pagination, le p_Step est mis à jour et déclenchera un nouveau filtrage par le filtre cust_pagination. Le filtre cust_pagination découpe ensuite le tableau en fonction de la valeur p_Step comme ci-dessous et ne renvoie que les enregistrements actifs sélectionnés dans la section pagination
var startIndex = nStep * nPageSize;
var endIndex = startIndex + nPageSize;
var arr = items.slice(startIndex, endIndex);
return arr;
J'aimerais pouvoir commenter, mais je vais juste devoir laisser ceci ici:
Scotty.NET la réponse et la restauration de user2176745 pour les versions ultérieures sont toutes deux géniales, mais elles manquent toutes les deux quelque chose que ma version D'AngularJS (v1.3.15) casse:
I n'est pas défini dans $ scope .makeTodos.
En tant que tel, le remplacement par cette fonction le corrige pour les versions angulaires plus récentes.
$scope.makeTodos = function() {
var i;
$scope.todos = [];
for (i=1;i<=1000;i++) {
$scope.todos.push({ text:'todo '+i, done:false});
}
};
Vue D'Ensemble : Pagination en utilisant
- ng-repeat
- uib-pagination
Afficher :
<div class="row">
<div class="col-lg-12">
<table class="table">
<thead style="background-color: #eee">
<tr>
<td>Dispature</td>
<td>Service</td>
<td>Host</td>
<td>Value</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in app.metricsList">
<td>{{x.dispature}}</td>
<td>{{x.service}}</td>
<td>{{x.host}}</td>
<td>{{x.value}}</td>
</tr>
</tbody>
</table>
<div align="center">
<uib-pagination items-per-page="app.itemPerPage" num-pages="numPages"
total-items="app.totalItems" boundary-link-numbers="true"
ng-model="app.currentPage" rotate="false" max-size="app.maxSize"
class="pagination-sm" boundary-links="true"
ng-click="app.getPagableRecords()"></uib-pagination>
<div style="float: right; margin: 15px">
<pre>Page: {{app.currentPage}} / {{numPages}}</pre>
</div>
</div>
</div>
</div>
Contrôleur JS :
app.controller('AllEntryCtrl',['$scope','$http','$timeout','$rootScope', function($scope,$http,$timeout,$rootScope){
var app = this;
app.currentPage = 1;
app.maxSize = 5;
app.itemPerPage = 5;
app.totalItems = 0;
app.countRecords = function() {
$http.get("countRecord")
.success(function(data,status,headers,config){
app.totalItems = data;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.getPagableRecords = function() {
var param = {
page : app.currentPage,
size : app.itemPerPage
};
$http.get("allRecordPagination",{params : param})
.success(function(data,status,headers,config){
app.metricsList = data.content;
})
.error(function(data,status,header,config){
console.log(data);
});
};
app.countRecords();
app.getPagableRecords();
}]);
Vous pouvez facilement le faire en utilisant la directive Bootstrap UI.
Cette réponse est une modification de la réponse donnée par @Scotty.NET, j'ai changé le code parce que la directive <pagination>
est obsolète maintenant.
Le code suivant génère la pagination:
<ul uib-pagination boundary-links="true" total-items="totalItems" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()" class="pagination" previous-text="‹" next-text="›" first-text="«" last-text="»"></ul>
Pour le rendre fonctionnel, utilisez ceci dans votre contrôleur:
$scope.filteredData = []
$scope.totalItems = $scope.data.length;
$scope.currentPage = 1;
$scope.itemsPerPage = 5;
$scope.setPage = function (pageNo) {
$scope.currentPage = pageNo;
};
$scope.pageChanged = function() {
var begin = (($scope.currentPage - 1) * $scope.itemsPerPage)
, end = begin + $scope.itemsPerPage;
$scope.filteredData = $scope.data.slice(begin, end);
};
$scope.pageChanged();
Reportez-vous à ceci pour plus d'options de pagination: Bootstrap UI Pagination Directive
Je voudrais ajouter ma solution qui fonctionne avec ngRepeat
et les filtres que vous utilisez avec elle sans utiliser un $watch
ou un tableau en tranches.
Les résultats de votre filtre seront paginés!
var app = angular.module('app', ['ui.bootstrap']);
app.controller('myController', ['$scope', function($scope){
$scope.list= ['a', 'b', 'c', 'd', 'e'];
$scope.pagination = {
currentPage: 1,
numPerPage: 5,
totalItems: 0
};
$scope.searchFilter = function(item) {
//Your filter results will be paginated!
//The pagination will work even with other filters involved
//The total number of items in the result of your filter is accounted for
};
$scope.paginationFilter = function(item, index) {
//Every time the filter is used it restarts the totalItems
if(index === 0)
$scope.pagination.totalItems = 0;
//This holds the totalItems after the filters are applied
$scope.pagination.totalItems++;
if(
index >= (($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage)
&& index < ((($scope.pagination.currentPage - 1) * $scope.pagination.numPerPage) + $scope.pagination.numPerPage)
)
return true; //return true if item index is on the currentPage
return false;
};
}]);
Dans le code HTML, assurez-vous d'appliquer vos filtres ngRepeat
avant le filtre de pagination.
<table data-ng-controller="myController">
<tr data-ng-repeat="item in list | filter: searchFilter | filter: paginationFilter track by $index">
<td>
{{item}}
</td>
<tr>
</table>
<ul class="pagination-sm"
uib-pagination
data-boundary-links="true"
data-total-items="pagination.totalItems"
data-items-per-page="pagination.numPerPage"
data-ng-model="pagination.currentPage"
data-previous-text="‹"
data-next-text="›"
data-first-text="«"
data-last-text="»">
</ul>