This content originally appeared on DEV Community and was authored by Lakshya Thakur
Today we will implement a Paginator class which will have the following API :-
// Initialization
const paginator = new Paginator(totalRecords,recordsPerPage,visiblePages);
// Usage
paginator.getActivePage();
paginator.gotoFirstPage();
paginator.gotoPrevPage();
paginator.gotoPage(page);
paginator.gotoNextPage();
paginator.gotoLastPage();
paginator.getVisiblePagesRange();
paginator.getActiveRecordsIndices();
The Class blueprint :-
class Paginator {
// Private class fields
#totalRecords;
#recordsPerPage;
#visiblePages;
#noOfPages;
#activePage;
#visiblePagesEndRange;
constructor(totalRecords, recordsPerPage, visiblePages) {
}
// Public class functions
getActivePage(){
}
gotoFirstPage() {
}
gotoPrevPage() {
}
gotoPage(page) {
}
gotoNextPage() {
}
gotoLastPage() {
}
getVisiblePagesRange() {
}
getActiveRecordsIndices() {
}
For all the explanations below, assume that totalRecords is 346, recordsPerPage and visiblePages are 6.
Let's start with the constructor :-
constructor(totalRecords, recordsPerPage, visiblePages) {
this.#recordsPerPage = recordsPerPage;
this.#totalRecords = totalRecords;
this.#noOfPages = Math.ceil(this.#totalRecords / this.#recordsPerPage);
this.#visiblePages = visiblePages;
this.#activePage = 1;
this.#visiblePagesEndRange = visiblePages;
}
- Here we are initializing all our private class fields to certain values.
#recordsPerPage,#totalRecordsand#visiblePagesstraight away get initialized to passed constructor parameters. - We can get the
#noOfPagesby dividing#totalRecordsby#recordsPerPage. - The
#activePageas the name denotes is the page which will be active/selected in your pagination UI. It is initialized to 1. - The
#visiblePagesEndRangewill be equivalent to#visiblePagesin the beginning and will help in maintaining a page range which comes into picture later on.
getActivePage(){
return this.#activePage;
}
The above is a public function to return the private field #activePage.
gotoFirstPage() {
this.#activePage = 1;
this.#visiblePagesEndRange = this.#visiblePages;
}
The above is a public function to set #activePage to 1 and #visiblePagesEndRange to #visiblePages (just like in constructor).
gotoPrevPage() {
if (this.#activePage > 1) {
this.#activePage -= 1;
if (this.#activePage % this.#visiblePages === 0) {
this.#visiblePagesEndRange = this.#activePage;
}
}
}
The above is a public function which can used to decrement #activePage by 1 every time it is executed. Generally executed on a click of Prev button or a < UI icon.
- The
#activePagecan only be decremented if it is greater than 1. - Also, suppose the
#activePageis currently 7 and this function gets executed,#activePagewill change to 6 and it's modulus with#visiblePageswill be equivalent to 0. What this means is that the#activePagenow belongs to a lower visible page range and it's necessary to reflect that by updating#visiblePagesEndRangeby setting it equal to#activePageitself.
gotoPage(page) {
this.#activePage = page;
}
The above is a public function which is used to set #activePage to the passed page parameter.
gotoNextPage() {
if (this.#activePage < this.#noOfPages) {
this.#activePage += 1;
if (this.#activePage > this.#visiblePagesEndRange) {
this.#visiblePagesEndRange += this.#visiblePages;
this.#visiblePagesEndRange = Math.min(this.#visiblePagesEndRange, this.#noOfPages);
}
}
}
The above is a public function which can be used to increment #activePage by 1 every time it is executed. Generally executed on a click of Next button or a > UI icon.
- The
#activePagecan only be incremented if it is less than the#noOfPages. - Also, suppose the
#activePageis currently 6 and this function gets executed,#activePagewill change to 7 but also go out of bounds of current#visiblePagesEndRangeso we will update that as well by an amount of#visiblePagesso that#visiblePagesEndRangewhich was earlier 6 now becomes 12. - Again,
#visiblePagesEndRangecannot exceed the#noOfPagesand that's why if adding#visiblePagesto it results in an out of bounds, we take that into consideration by taking the minimum as shown above.
gotoLastPage() {
this.#activePage = this.#noOfPages;
this.#visiblePagesEndRange = this.#noOfPages;
}
The above is a public function to set both #activePage and #visiblePagesEndRange to #noOfPages.
getVisiblePagesRange() {
let beginningVisiblePage;
let endingVisiblePage;
if (this.#visiblePagesEndRange % this.#visiblePages === 0) {
beginningVisiblePage = this.#visiblePagesEndRange - this.#visiblePages + 1;
}
else {
beginningVisiblePage =
this.#visiblePagesEndRange - (this.#visiblePagesEndRange % this.#visiblePages) + 1;
}
endingVisiblePage = this.#visiblePagesEndRange;
return {
beginningVisiblePage,
endingVisiblePage
};
}
The above is a public function which is used to retrieve beginningVisiblePage and endingVisiblePage by the means of which you can generate the respective UI page elements dynamically.
-
For the
beginningVisiblePage:-- If
#visiblePagesEndRange % this.#visiblePagesis 0, thenbeginningVisiblePagecan be set to#visiblePagesEndRange - this.#visiblePages + 1 - Otherwise, consider a scenario when the
#visiblePagesEndRangewill be 58 (this would happen in the last page range). Now 58 % 6 isn't 0 but 4. So we would need to subtract 4 from 58 and add 1 to it to get the correctbeginningVisiblePagewhich will be 55. (Final page range is actually 55,56,57 and 58 for our current example).
- If
The
endingVisiblePagewill always be equal to#visiblePagesEndRange.
getActiveRecordsIndices() {
let beginningRecordIndex = (this.#activePage - 1) * this.#recordsPerPage;
let endingRecordIndex = Math.min(
beginningRecordIndex + this.#recordsPerPage,
this.#totalRecords
);
return { beginningRecordIndex, endingRecordIndex };
}
}
The above is a public function which is used to retrieve beginningRecordIndex and endingRecordIndex by the means of which you can generate the respective UI record elements dynamically.
- The
beginningRecordIndexwill be equal to#activePage-1multiplied by the#recordsPerPage. - The
endingRecordIndexwill be minimum ofbeginningRecordIndex + #recordsPerPageand#totalRecords.
Below is a codepen where you can see the Paginator class in action. Here there is an additional #validate function which isn't important to basic implementation. And yes I haven't really applied the best CSS out there !!
I hope you enjoyed reading this piece :D. Also feel free to give any feedback. I just like to make something in vanilla JS every once in a while and not think too much about production readiness while making it. That's the part where you can come in and share your approaches.
This content originally appeared on DEV Community and was authored by Lakshya Thakur
Lakshya Thakur | Sciencx (2021-07-04T08:01:45+00:00) Implementing Pagination feature in Vanilla JS. Retrieved from https://www.scien.cx/2021/07/04/implementing-pagination-feature-in-vanilla-js/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.


