How to Sort only the current page using Jquery Datatable

Before asking how to sort only current page we should answer following questions:

  • Why do we want to do such sorting?
  • Should we do it?
  • Does it have any sense?
  • What are the implications of such decision?

When we want to execute a query and display the result list we are dealing with:

  • searching criteria
  • sorting criteria
  • pagination

These three elements are strongly related and they clearly define what user sees on the screen.
We can have for example following description:

There is a list of actors. It is sorted by name and divided into pages (50 items per page). And we are on the third page.

When we have such rules then user has good orientation in this list. He sees Michael Caine at the top and Shon Connery on the bottom of the page. When he wants to find Robert Duvall he knows he should go few pages further. And when he wants to see these actors sorted by age he simply resorts the lists and returns to first page.

But what if we provide additional sorting only for current page? This would disturb cohesion of above system. How would it sound if we say to user:

You are now seeing third page of sorted-by-name list of actors resorted (page) by age.

What can this user gain by resorting only current page? Age hierarchy of actors with name starting with 'C'? At the top of the page there will be the oldest actor from this page. But user doesn't know if it the oldest actor in all the list. And if not then on which page should he look for older one? Such resorting is worthless and it overrides initial sorting (which had some value).

Such resorting can also lead user to serious confusion. He can loose his orientation about original sorting and page sorting.

Conclusions:

I don't see any sense in providing sorting for single page. I find it harmful. So you should use it only if you have strong arguments for it.


Update 1

Although I agree with rtruszk, I still think a solution should be found/explored if 0) you have no choice or 1) your client is not willing to discuss UX changes.

Working Example: http://jsfiddle.net/ebRXw/63/

I was able to accomplish what you were after by filtering out the currently visible rows from the DataTable. I tried my best to find a solution within DataTables, and one may exist, but in the end I used jQuery and a hash table to identify and filter out the currently visible rows.

I'm sure this can be optimized further. Hopefully, it gets you moving in the right direction.

$(document).ready(function () {

    var table = $('#example').DataTable({
        "columnDefs": [{
            "targets": [0],
                "visible": false,
                "searchable": true
        }]
    });

    // Show page 0
    table.page(0).draw(false);
    // Sort by column 1 (Name)
    table.order([1, 'asc']).draw(false);

    $("#ReloadTable").click(function () {
        // Clear the current filter
        oTable = $('#example').dataTable();
        oTable.fnFilter('', 0);
        oTable.fnFilter('');

        // Reset all "visible" values in the first cell
        var table = $('#example').DataTable();
        table.rows().indexes().each(function (idx) {
            var d = table.row(idx).data();
            table.row(idx).data()[0] = 0;
            d.counter++;
            table.row(idx).data(d);
        });
    });

    $("#FilterCurrentPage").click(function () {
        // Create a hash of the index of currently visible rows
        var h = new Object();
        var x = $('.odd,.even').filter(function () {
            var idx = $(this)[0]._DT_RowIndex;
            h[idx] = idx;
            return this.style.display == ''
        });

        // update the first value based on the currently visible rows
        var table = $('#example').DataTable();
        table.rows().indexes().each(function (idx) {
            var d = table.row(idx).data();
            if (h.hasOwnProperty(idx)) {
                table.row(idx).data()[0] = 1;
            }
            d.counter++;
            table.row(idx).data(d);
        });

        // filter rows with a value of 1 in the first cell
        oTable = $('#example').dataTable();
        oTable.fnFilter(1, 0);
    });
});

Update 0

I still haven't found a workaround, but I'm convinced one exists. The code below will select and return the current visible rows in your datatable.

var x = $('.odd,.even').filter(function () {
    $(this).addClass('selected'); // Select the visible rows
    return this.style.display == '' 
});

From the DataTables maintainer:

Is there an easy way to tell datatables that I want to sort and redraw only current pagination?

In DataTables 1.9- no, there isn't a way of doing that, but in 1.10 you can use table.order( ... ).draw( false ); to preserve paging. 1.10 pre beta is available in git if you want to give it a bash :-)

Allan

via datatables: sort only current pagination of table

However, you might be able to get the current visible rows, sort them, and display them somehow. The below code provides the current visible rows after filtering.

var table = $('#example').DataTable();
table.$('tr', {"filter":"applied"});

See also:

  • jquery DataTables. How to get filtered (visible) rows
  • fnGetData of visible rows only
  • Retrieving row data after filtering JQuery Datatables