August 07 2018

JavaScript - Pure Pagination Logic in Vanilla JS / TypeScript

Below is a pure pagination function written in Vanilla JS (with a touch of TypeScript for typed parameter support) that you can use to paginate any array or list of items in JavaScript.

The pure JavaScript version is available as the npm package jw-paginate, you can add it to your project by running npm install jw-paginate and import it into your code with import paginate from 'jw-paginate';

Source code is available on GitHub at https://github.com/cornflourblue/jw-paginate

I've also created a couple of pagination components in React and Angular that use the below paginate function under the hood, you can see demos of them running at the following links:


JavaScript Paginate Function Usage

The paginate function accepts the following parameters:

  • totalItems (required) - the total number of items to be paged
  • currentPage (optional) - the current active page, defaults to the first page
  • pageSize (optional) - the number of items per page, defaults to 10
  • maxPages (optional) - the maximum number of page navigation links to display, defaults to 10

The output of the paginate function is an object containing all the information needed to display the current page of items in the view and the page navigation links.

Below are some example inputs and outputs to give you a better idea of how the function works, you can also tinker with them live on StackBlitz here.

paginate(150)

totalItems: 150

{ 
    totalItems: 150,
    currentPage: 1,
    pageSize: 10,
    totalPages: 15,
    startPage: 1,
    endPage: 10,
    startIndex: 0,
    endIndex: 9,
    pages: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
}


paginate(150, 7)

totalItems: 150, currentPage: 7

{ 
    totalItems: 150,
    currentPage: 7,
    pageSize: 10,
    totalPages: 15,
    startPage: 2,
    endPage: 11,
    startIndex: 60,
    endIndex: 69,
    pages: [ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] 
}


paginate(150, 7, 15)

totalItems: 150, currentPage: 7, pageSize: 15

{ 
    totalItems: 150,
    currentPage: 7,
    pageSize: 15,
    totalPages: 10,
    startPage: 1,
    endPage: 10,
    startIndex: 90,
    endIndex: 104,
    pages: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] 
}


paginate(150, 7, 15, 5)

totalItems: 150, currentPage: 7, pageSize: 15, maxPages: 5

{ 
    totalItems: 150,
    currentPage: 7,
    pageSize: 15,
    totalPages: 10,
    startPage: 5,
    endPage: 9,
    startIndex: 90,
    endIndex: 104,
    pages: [ 5, 6, 7, 8, 9 ] 
}


JavaScript Pagination Logic

Below are the nuts and bolts of how the pagination logic is implemented. It's a pure JavaScript function except for the : number typings in a few spots which are TypeScript. The version available on npm has been transpiled into pure JavaScript so there is no dependency on TypeScript or anything else.

function paginate(
    totalItems: number,
    currentPage: number = 1,
    pageSize: number = 10,
    maxPages: number = 10
) {
    // calculate total pages
    let totalPages = Math.ceil(totalItems / pageSize);

    // ensure current page isn't out of range
    if (currentPage < 1) {
        currentPage = 1;
    } else if (currentPage > totalPages) {
        currentPage = totalPages;
    }

    let startPage: number, endPage: number;
    if (totalPages <= maxPages) {
        // total pages less than max so show all pages
        startPage = 1;
        endPage = totalPages;
    } else {
        // total pages more than max so calculate start and end pages
        let maxPagesBeforeCurrentPage = Math.floor(maxPages / 2);
        let maxPagesAfterCurrentPage = Math.ceil(maxPages / 2) - 1;
        if (currentPage <= maxPagesBeforeCurrentPage) {
            // current page near the start
            startPage = 1;
            endPage = maxPages;
        } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) {
            // current page near the end
            startPage = totalPages - maxPages + 1;
            endPage = totalPages;
        } else {
            // current page somewhere in the middle
            startPage = currentPage - maxPagesBeforeCurrentPage;
            endPage = currentPage + maxPagesAfterCurrentPage;
        }
    }

    // calculate start and end item indexes
    let startIndex = (currentPage - 1) * pageSize;
    let endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);

    // create an array of pages to ng-repeat in the pager control
    let pages = Array.from(Array((endPage + 1) - startPage).keys()).map(i => startPage + i);

    // 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
    };
}

export = paginate;

 

Web Development Sydney

Feel free to contact me if you're looking for a web developer in Sydney, I also provide remote contracting services for clients outside Sydney.

 


Sponsored by