Using jQuery to Sort and Paginate a Table

Posted by: Irvin Dominin , on 7/23/2015, in Category jQuery and ASP.NET
Views: 60880
Abstract: Use jQuery to Sort a table. Also add Pagination to the table with Previous and Next links to move back and forth.

Rather than overwhelming our visitors with a page that contains a table with hundreds of rows, pagination allows us to display a small subset of data at a given point of time. You can then provide navigation links that allow users to move through the other subsets of data, with ease.

 

The jQuery Pagination and Sorting example is shown in the figure below with Previous and Next navigation links to move back and forth:

s3-pagination

In this article, we will see how to sort and paginate a Table. Create a new file called ‘TableSortPaginate.html’ and then add the following markup:

<body>
    <table border="1" id="movie">
        <thead>
            <tr>
                <th class="ranking">Ranking</th>
                <th class="title">Movie</th>
                <th class="year">Release Year</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>1</td>
                <td>Citizen Kane</td>
                <td>1941</td>
            </tr>
            <tr>
                <td>2</td>
                <td>The Godfather</td>
                <td>1972</td>
            </tr>
            <tr>
                <td>2</td>
                <td>The Godfather</td>
                <td>1972</td>
            </tr>
         ...
        </tbody>
    </table>

  
</body>

The HTML markup contains a table with a <thead> and <tbody>.

Using jQuery to Sort a Table

Let’s setup the script now. We will first add Sorting support to the table. I have used inline comments here to facilitate understanding:

<script type='text/javascript'>

    $(function () {
        // Selectors for future use
        var myTable = "#movie";
        var myTableBody = myTable + " tbody";
        var myTableRows = myTableBody + " tr";
        var myTableColumn = myTable + " th";

        // Starting table state
        function initTable() {

            // Increment the table width for sort icon support
            $(myTableColumn).each(function () {
                var width = $(this).width();
                $(this).width(width + 40);
            });

            // Set the first column as sorted ascending
            $(myTableColumn).eq(0).addClass("sorted-asc");

            //Sort the table using the current sorting order
            sortTable($(myTable), 0, "asc");

        }

        // Table starting state
        initTable();

        // Table sorting function
        function sortTable(table, column, order) {
            var asc = order === 'asc';
            var tbody = table.find('tbody');

            // Sort the table using a custom sorting function by switching 
            // the rows order, then append them to the table body
            tbody.find('tr').sort(function (a, b) {
                if (asc) {
                    return $('td:eq(' + column + ')', a).text()
                        .localeCompare($('td:eq(' + column + ')', b).text());
                } else {
                    return $('td:eq(' + column + ')', b).text()
                        .localeCompare($('td:eq(' + column + ')', a).text());
                }
            }).appendTo(tbody);

        }

        // Heading click
        $(myTableColumn).click(function () {

            // Remove the sort classes for all the column, but not the first
            $(myTableColumn).not($(this)).removeClass("sorted-asc sorted-desc");

            // Set or change the sort direction
            if ($(this).hasClass("sorted-asc") || $(this).hasClass("sorted-desc")) {
                $(this).toggleClass("sorted-asc sorted-desc");
            } else {
                $(this).addClass("sorted-asc");
            }

            //Sort the table using the current sorting order
            sortTable($(myTable),
                        $(this).index(),
                        $(this).hasClass("sorted-asc") ? "asc" : "desc");

        });

    });

</script>

The code defines a sortTable function that takes a table id, a column index (0-based) and a sorting direction. The sorting function uses jQuery sort() and eq() method.

Note: The sort method is not part of jQuery (officially), but is a proxied javascript Array.sort that makes the selector result object "act like an array".

In the sorting function, we have the “current” and previous element being sorted (in our case the rows) and we use the eq() function to get the column sorted. eq() will help us here because it reduces the set of matched elements to the one at the specified index.

The doc states: Given a jQuery object that represents a set of DOM elements, the .eq() method constructs a new jQuery object from one element within that set. The supplied index identifies the position of this element in the set.

In the sort function, we compare each td cell text with the next and obtain a sorted table.

With the function sortTable ready for use, we can attach an event handler to the click event on the th element (table header) and trigger the sort for the selected column.

When a column is sorted ascending or descending, we add a specific class to the td element. When a column is clicked, if it’s the currently sorted one, we switch the sort order. Alternatively, we remove the classes on all the columns and attach the new class to the selected column.

Go through the code a couple of times, along with the inline comments to understand what’s happening.

Using jQuery to Paginate a Table

With the sorting functionality working as desired, let’s now add pagination to the table. Our table markup remains the same, except that now we will add a div with two hyperlinks to navigate the table.

<div>
    <a href="#" class="paginate" id="previous">Previous</a> |
    <a href="#" class="paginate" id="next">Next</a>
</div>

Let’s take a look at the code. I have on purpose replaced the Table Sorting code with ellipses (…) so that we can focus only on the pagination aspect of the table. However ‘TableSortPaginate.html’ contains the entire code both for Sorting as well as Pagination:

<script type='text/javascript'>

$(function () {
    // Selectors for future use
    var myTable = "#movie";
    var myTableBody = myTable + " tbody";
    var myTableRows = myTableBody + " tr";
    var myTableColumn = myTable + " th";

    // Starting table state
    function initTable() {
        $(myTableBody).attr("data-pageSize", 4);
        $(myTableBody).attr("data-firstRecord", 0);
        $('#previous').hide();
        $('#next').show();

        // Increment the table width for sort icon support
        ...

        // Start the pagination
        paginate(parseInt($(myTableBody).attr("data-firstRecord"), 10),
                 parseInt($(myTableBody).attr("data-pageSize"), 10));
    }


    // Table sorting function
    function sortTable(table, column, order) {
         ...

    }

    // Heading click
    $(myTableColumn).click(function () {
        ...

        // Start the pagination
        paginate(parseInt($(myTableBody).attr("data-firstRecord"), 10),
                 parseInt($(myTableBody).attr("data-pageSize"), 10));
    });

    // Pager click
    $("a.paginate").click(function (e) {
        e.preventDefault();
        var tableRows = $(myTableRows);
        var tmpRec = parseInt($(myTableBody).attr("data-firstRecord"), 10);
        var pageSize = parseInt($(myTableBody).attr("data-pageSize"), 10);

        // Define the new first record
        if ($(this).attr("id") == "next") {
            tmpRec += pageSize;
        } else {
            tmpRec -= pageSize;
        }
        // The first record is < of 0 or > of total rows
        if (tmpRec < 0 || tmpRec > tableRows.length) return

        $(myTableBody).attr("data-firstRecord", tmpRec);
        paginate(tmpRec, pageSize);
    });

    // Paging function
    var paginate = function (start, size) {
        var tableRows = $(myTableRows);
        var end = start + size;
        // Hide all the rows
        tableRows.hide();
        // Show a reduced set of rows using a range of indices.
        tableRows.slice(start, end).show();
        // Show the pager
        $(".paginate").show();
        // If the first row is visible hide prev
        if (tableRows.eq(0).is(":visible")) $('#previous').hide();
        // If the last row is visible hide next 
        if (tableRows.eq(tableRows.length - 1).is(":visible")) $('#next').hide();
    }

    // Table starting state
    initTable();


});

The code defines two data-attributes on the tbody element representing the current first row displayed on the table, and maximum size of each page. These attribute will be used in the code to define the elements to display, according to the current page.

In the paginate function, we calculate the element to display by using jQuery slice method which reduces the set of matched elements to a subset specified by a range of indices.

The doc states: Given a jQuery object that represents a set of DOM elements, the .slice() method constructs a new jQuery object containing a subset of the elements specified by the start and, optionally, end argument. The supplied start index identifies the position of one of the elements in the set; if end is omitted, all elements after this one will be included in the result.

Using slice, we obtain a subset of rows according to the current first-record element, incremented by the page size. Similarly the last element is the previously calculated new first element incremented by the page size.

Finally using jQuery :is method and :visible selector, we can check if the first/last element is visible and display the Next/Previous button accordingly.

Go through the code a couple of times along with the inline comments to get a grip of what’s going on.

Now we have the code to sort and paginate a table; the initTable function is triggered to setup an initial display state of the grid. The function uses paginate and sortTable functions to sort the grid by the first column ascending, and with a pagination of 4 rows per page.

In a future article, I will demonstrate how to create a SortandPaginate plugin which can be used on any table with the given structure.

Note: For a Table containing thousands of rows, client side pagination may not be a very good idea, as what you are essentially doing is loading all these rows in the browser and then displaying only a subset of data. In such cases, with a loaded table, server-side pagination is the way to go. Server-side pagination is beyond the scope of this book, but for those interested, you can read an article that shows how to do it using ASP.NET WebAPI and Knockout.js over here https://www.dotnetcurry.com/aspnet/942/sorting-pagination-grid-aspnet-webpai-knockoutjs

Live Demo: http://www.jquerycookbook.com/demos/S3-TablesTabsPanels/25-TableSortPaginate.html

If you liked this article, take a look at a new jQuery book The Absolutely Awesome jQuery Cookbook which contains scores of practical jQuery/jQueryUI recipes you can use in your projects right away.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Irvin Dominin is currently working as lead of a technical team in SISTEMI S.p.A. (Turin, Italy) on .NET, jQuery and windows Projects. He is an active member on StackOverflow. You can reach him at: irvin[dot]dominin[attherate]gmail[dot]com or on LinkedIn


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!