Reputation: 718
I've built a custom pagination with this directive:
app.directive('postsGenreLink', function() {
return {
restrict: 'EA',
templateUrl: myLocalized.partials + 'posts-genre-link.html',
controller: ['$scope', '$element', '$routeParams', function($scope, $element, $routeParams) {
var currentGenrePage = (!$routeParams.page) ? 1 : parseInt($routeParams.page),
linkPrefix = (!$routeParams.slug) ? 'page/' : 'genre/' + $routeParams.slug + '/page/';
$scope.postsGenreLink = {
prevLink: linkPrefix + (currentGenrePage - 1),
hopLink: linkPrefix,
nextLink: linkPrefix + (currentGenrePage + 1),
sep: (!$element.attr('sep')) ? '|' : $element.attr('sep'),
prevLabel: (!$element.attr('prev-label')) ? 'Previous Page' : $element.attr('prev-label'),
nextLabel: (!$element.attr('next-label')) ? 'Next Page' : $element.attr('next-label'),
hopLabel: (!$element.attr('Jump')) ? 'Jump' : $element.attr('Jump')
};
}]
};
});
This is my posts-genre-link.html
:
<nav aria-label="...">
<ul class="pagination pt-3">
<li class="page-item" ng-class="{'disabled' : currentGenrePage == 1}">
<a class="page-link" href="{{postsGenreLink.prevLink}}">Previous</a>
</li>
<li ng-repeat="i in [].constructor(totalPages) track by $index" class="page-item" ng-class="{'active' : currentGenrePage == $index + 1}"><a class="page-link" href="{{postsGenreLink.hopLink+($index + 1)}}">{{$index + 1}}</a></li>
<li class="page-item" ng-class="{'disabled' : currentGenrePage >= totalPages}">
<a class="page-link" href="{{postsGenreLink.nextLink}}">Next</a>
</li>
</ul>
</nav>
The totalPages
is a scope variable defined in the controller $scope.totalPages = parseInt(headers('X-WP-TotalPages'));
and it basically contains the number of the pages.
This is how it looks like:
My problem is when this value is very high; I don't want to display 200-300 pages, I would like to display only the currentGenrePage
and 2 pages behind and forward with the classic dots to underline that there are more pages. How can I handle this?
Upvotes: 1
Views: 3086
Reputation: 718
This is how i solved "graphically" (hiding the number if the current page plus 1 is lower then the $index
or current Page less 3 higher than the $index
.
<nav aria-label="...">
<ul class="pagination pt-3">
<li class="page-item" ng-class="{'disabled' : currentGenrePage == 1}">
<a class="page-link" href="{{postsGenreLink.prevLink}}">Previous</a>
</li>
<li class="page-item disabled" ng-class="{'notshow' : currentGenrePage == 1 || currentGenrePage == 2 || currentGenrePage == 3}">
<a class="page-link" href="">...</a>
</li>
<li ng-repeat="i in [].constructor(totalPages) track by $index" class="page-item" ng-class="{'active' : currentGenrePage == $index + 1, 'notshow' : currentGenrePage + 1 < $index || currentGenrePage - 3 > $index}"><a class="page-link" href="{{postsGenreLink.hopLink+($index + 1)}}">{{$index + 1}}</a></li>
<li class="page-item disabled" ng-class="{'notshow' : currentGenrePage == totalPages || currentGenrePage == totalPages -1 || currentGenrePage == totalPages - 2}">
<a class="page-link" href="">...</a>
</li>
<li class="page-item" ng-class="{'disabled' : currentGenrePage >= totalPages}">
<a class="page-link" href="{{postsGenreLink.nextLink}}">Next</a>
</li>
</ul>
</nav>
where:
.notshow {
display:none;
}
Upvotes: 1
Reputation: 19748
If you want to start with something relatively simple I wrote a pagination directive here:
https://plnkr.co/edit/W85f8IYXHLNmVkmm?p=preview
.directive('pagingDisplay', function() {
return {
scope: {
startAt: '=', //Two way binding for which element to start at
numPerPage: '@', //Number of elements we want per page
totalElements: '@', //Total number of elements in the collection
maxButtons: '@' //Maximum number of page number buttons to show
},
templateUrl: 'templateId.html',
link: function(scope, iElem, iAttrs) {
//Computed when the num per page and total are provided
var _totalPages = 0;
//Max page buttons to show (default 5)
var _maxPages = 5;
scope.model = {
selectedPage: 0,
showForward: false,
showBackward: true
};
/**
* Uses the current selected page, num pages, and max pages to
* create an array that corresponds to the page numbers shown
*/
function genPagesArray(numPages) {
scope.pages = [];
if (numPages <= _maxPages) {
for (var i = 0; i < numPages; i++) {
scope.pages.push(i);
}
} else {
var showEndPage = true,
showStartPage = true;
var halfPages = Math.floor((_maxPages - 1) / 2);
var firstPage = Math.max(0, scope.model.selectedPage - halfPages);
var lastPage = firstPage + _maxPages;
if (lastPage > _totalPages) {
firstPage += (_totalPages - lastPage);
lastPage = _totalPages;
}
for (var i = firstPage, x = 0; i < lastPage && x < _maxPages; x++, i++) {
scope.pages.push(i)
if (i == numPages - 1)
showEndPage = false;
if (i == 0)
showStartPage = false;
}
if (showEndPage) {
scope.pages.pop();
scope.pages.push(numPages - 1);
}
if (showStartPage) {
scope.pages.shift();
scope.pages.unshift(0);
}
}
}
genPagesArray(5);
scope.$watch('totalElements', function(newVal) {
var intVal = scope.totalElements;
if (intVal && !isNaN(intVal = parseInt(intVal))) {
_totalPages = Math.ceil(intVal / scope.numPerPage)
if (scope.model.selectedPage > _totalPages) {
scope.firstPage();
} else {
genPagesArray(_totalPages);
}
}
});
scope.$watch('maxButtons', function(newVal) {
var intVal = scope.maxButtons;
if (intVal && !isNaN(intVal = parseInt(intVal))) {
_maxPages = intVal;
genPagesArray(_totalPages);
}
});
scope.prevPage = function() {
if (scope.model.selectedPage > 0)
scope.changeSelectedPage(scope.model.selectedPage - 1)
}
scope.nextPage = function() {
if (scope.model.selectedPage < _totalPages - 1)
scope.changeSelectedPage(scope.model.selectedPage + 1)
}
scope.lastPage = function() {
scope.changeSelectedPage(_totalPages - 1)
}
scope.firstPage = function() {
scope.changeSelectedPage(0)
}
scope.changeSelectedPage = function(pageToSelect) {
scope.model.selectedPage = pageToSelect;
scope.startAt = pageToSelect * parseInt(scope.numPerPage);
genPagesArray(_totalPages)
}
}
}
})
The directive template
<div>
<span class="pagination-button" ng-click="firstPage()"> |< </span><span class="pagination-button" ng-click="prevPage()"> << </span><span class="pagination-button" ng-click="changeSelectedPage(page)" ng-class="{'selected':model.selectedPage == page}"
ng-repeat="page in pages track by $index">
{{(page+1)}}
</span><span class="pagination-button" ng-click="nextPage()"> >> </span><span class="pagination-button" ng-click="lastPage()"> >| </span>
</div>
CSS
.pagination-button {
border: 1px solid #ccc;
border-radius: 4px;
padding: 10px;
display: inline-block;
width: 20px;
text-align: center;
margin-right: 2px;
/* Disable Text Selection */
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently
supported by Chrome and Opera */
}
.pagination-button:hover {
background-color: #ddffdd;
cursor: pointer;
}
.pagination-button:active,
.pagination-button.selected {
background-color: #ccffaa;
}
Usage
<paging-display num-per-page="5" max-buttons="{{myctrl.maxPageButtons}}" total-elements="{{myctrl.filtered.length}}" start-at="myctrl.startAt">
</paging-display>
If you want something a bit more robust tested/widely used there is also a pagination directive in ui-bootstrap.
https://angular-ui.github.io/bootstrap/
Upvotes: 1