Skip to content

Instantly share code, notes, and snippets.

@creativecoder
Last active September 19, 2015 00:42
Show Gist options
  • Save creativecoder/52001c7484e402c82013 to your computer and use it in GitHub Desktop.
Save creativecoder/52001c7484e402c82013 to your computer and use it in GitHub Desktop.
vue.js pagination component
var _ = require('lodash');
/*
Example:
<pagination
current-page='@{{@ currentPage}}'
total-items='@{{totalItems}}'
per-page='@{{perPage}}'>
</pagination>
*/
module.exports = {
template: '<nav>' +
'<ul class="pagination">' +
'<li v-if="boundaryLinks" v-class="disabled: currentPage === 1">' +
'<a href="#" aria-label="First" v-on="click: setPage(1)">' +
'<span aria-hidden="true">{{{ firstText }}}</span>' +
'</a>' +
'</li>' +
'<li v-if="directionLinks" v-class="disabled: currentPage === 1">' +
'<a href="#" aria-label="Previous" v-on="click: setPage(currentPage - 1)">' +
'<span aria-hidden="true">{{{ prevText }}}</span>' +
'</a>' +
'</li>' +
'<li v-class="active : page.value == this.currentPage" v-repeat="page in pages" v-on="click: setPage(page.value)">' +
'<a href="#">{{ page.label }}</a>' +
'</li>' +
'<li v-if="directionLinks" v-class="disabled: currentPage === totalPages">' +
'<a href="#" aria-label="Next" v-on="click: setPage(currentPage + 1)">' +
'<span aria-hidden="true">{{{ nextText }}}</span>' +
'</a>' +
'</li>' +
'<li v-if="boundaryLinks" v-class="disabled: currentPage === totalPages">' +
'<a href="#" aria-label="Last" v-on="click: setPage(totalPages)">' +
'<span aria-hidden="true">{{{ lastText }}}</span>' +
'</a>' +
'</li>' +
'</ul>' +
'</nav>',
props: {
currentPage: {
type: Number,
required: true,
twoWay: true,
default: 1,
},
totalItems: {
type: Number,
required: true,
},
perPage: {
type: Number,
default: 10,
},
// How many pages to display in the list before and after the current page
displayRange: {
type: Number,
default: 3,
},
// Whether to display Prev/Next Buttons
directionLinks: {
type: Boolean,
default: true,
},
nextText: {
type: String,
default: 'Next',
},
prevText: {
type: String,
default: 'Prev',
},
// Whether to display First/Last buttons
boundaryLinks: {
type: Boolean,
default: true,
},
firstText: {
type: String,
default: 'First',
},
lastText: {
type: String,
default: 'Last',
},
},
computed: {
totalPages: function() {
return Math.ceil(this.totalItems/this.perPage);
},
pages: function() {
return this.paginate();
},
showDirectionLinks: function() {
console.log(this.directionLinks);
return this.directionLinks;
}
},
methods:{
paginate: function() {
var threshold = 2 * this.displayRange + 3,
lowerLimit = this.displayRange + 3,
upperLimit = this.totalPages - this.displayRange - 2,
displayFirst,
displayLast,
rangeLocation,
rangeLabel = '...',
pages = []
;
// We need leading and/or trailing `...` b/c there are too many pages to display all at once
if (this.totalPages > threshold) {
// We're at the lower end of the page range: `1,2,3,4,5,...`
if (this.currentPage < lowerLimit) {
rangeLocation = 'lower';
displayFirst = 1;
displayLast = threshold;
// We're at the upper end of the page range: `...,24,25,26,27,28`
} else if (upperLimit < this.currentPage) {
rangeLocation = 'upper';
displayFirst = this.totalPages - 2 * this.displayRange - 1;
displayLast = this.totalPages + 1;
// We're somewhere in the middle of the page range: `...,11,12,13,14,...`
} else {
rangeLocation = 'middle';
displayFirst = this.currentPage - this.displayRange;
displayLast = this.currentPage + this.displayRange + 1;
}
// We don't need any leading/trailing `...` because all the pages fit in the list
} else {
rangeLocation = 'n/a';
displayFirst = 1;
displayLast = this.totalPages + 1;
}
// Build page list
// Leading `...`
if ('middle' === rangeLocation || 'upper' === rangeLocation) {
pages.push({label: rangeLabel, value: this.currentPage - this.displayRange - 2});
}
// Page list
for (let pageNumber of _.range(displayFirst, displayLast)) {
pages.push({label: pageNumber, value: pageNumber});
}
// Trailing `...`
if ('lower' === rangeLocation || 'middle' === rangeLocation) {
pages.push({label: rangeLabel, value: this.currentPage + this.displayRange + 2})
}
return pages;
},
setPage: function(page) {
if (page == '' || page < 1 || page > this.totalPages) return;
if (this.currentPage != page) {
this.currentPage = page;
this.$dispatch('pageChange');
}
},
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment