I was recently tasked with implementing pagination for an array of values (in some instances, over 2400 of them) and instead of using an existing library, I opted to write my own pagination logic and put it into an Aurelia value converter.
There are a lot of ways you can achieve this, you can use slice
, you can use filter
and reduce
as well. The solution I ended up coming up with uses slice because it produces the easiest to read and simple code. Performance-wise, I do believe that filter
comes out on top, but that isn’t our concern here.
const paginate = (items, page = 1, perPage = 10) => items.slice(perPage \* (page - 1), perPage \* page);
However, if you want something a little more descriptive, you can get a little more verbose and produce something that while not nearly as concise, gives you some more details.
In my instance, I wanted to return the next and previous pages, as well as the total number of pages and items for each page that is being paginated. While you get a more verbose method, it becomes a lot more useful.
const paginate = (items, page = 1, perPage = 10) => {
const offset = perPage \* (page - 1);
const totalPages = Math.ceil(items.length / perPage);
const paginatedItems = items.slice(offset, perPage \* page);
return {
previousPage: page - 1 ? page - 1 : null,
nextPage: (totalPages > page) ? page + 1 : null,
total: items.length,
totalPages: totalPages,
items: paginatedItems
};
};
If you’re using Aurelia, here is a value converter which will give you array pagination that can be used on a repeat.for
or anywhere else you’re display items from an array. If you’re not using Aurelia, you can stop reading here, the above is what you’re after.
export class PaginateValueConverter {
toView(array, page = 1, perPage = 10) {
if (!array) {
return array;
}
const paginationObject = paginate(array, page, perPage);
return paginationObject.items;
}
}
You can then use this value converter in your Aurelia applications like this:
- ${item.name}
You would probably have a currentPage
variable in your view-model, where you increment the value if a button or link is pressed, maybe a row of numbers.
- ${item.name}