bur
bur

Reputation: 776

DataTables not paging correctly with popstate

I'm using DataTables with serverSide processing. On popstate the table is redrawn with loaded values. Everything is working nicely except for one problem: when I go from a state where the page for the loaded state isn't available, it won't load the correct page for the loaded state, if that makes sense.

So for example:

  1. If I'm in a state with 2 or more pages available, and then push the "back" button to a state on page 2, it will correctly load page 2.
  2. If I'm in a state with only 1 page available, and then push the "back" button to a state on page 2, it will load page 1.

Edit: I realize now that this is because of this in the page() doc:

Note that if you attempt to show a page which does not exist using the set format of this method, DataTables will not throw an error, but rather reset the paging to the first page.

The problem is that with serverSide processing, DataTables doesn't know how many pages there are until the table is drawn, so when the number of pages increases after doing a manual draw(), this leads to the problem I'm describing. There doesn't seem to be a way to coerce DataTables to go to the page anyway, so the only option would be to draw twice.

Here's the (simplified) code:

$(document).ready(function() {
    myTable.on("draw", function() {
        setState(); // history.replaceState or history.pushState
        saveTableOrder(); // save to localStorage
        saveTableLength(); // save to localStorage
    });
    
    $(window).on("popstate", function() {
        myTable
            .search(loadTableSearch()) // load from history.state
            .order(loadTableOrder()) // load from history.state or localStorage
            .page.len(loadTableLength()) // load from history.state or localStorage
            .page(loadTablePage()-1) // zero-indexed; load from history.state
            .draw(false); // same result with "full-hold" argument
    });
});

Upvotes: 0

Views: 48

Answers (1)

bur
bur

Reputation: 776

It seems that the only way around this is to draw the table twice in these cases. Hopefully there is a better solution that I'm missing, but I don't think so.

$(document).ready(function() {
    let redraw = false;

    myTable.on("draw", function() {
        // make sure we don't just reload page 1
        let page = loadTablePage();
        redraw = redraw && page > 1 && page <= myTable.page.info().pages;
        if (redraw) {
            redraw = false;
            myTable.page(page-1).draw("page");
        }
        else {
            setState(); // history.replaceState or history.pushState
            saveTableOrder(); // save to localStorage
            saveTableLength(); // save to localStorage
        }
    });
    
    $(window).on("popstate", function() {
        let page = loadTablePage(); // load from history.state
        redraw = page > 1 && page > myTable.page.info().pages;
        
        myTable
            .search(loadTableSearch()) // load from history.state
            .order(loadTableOrder()) // load from history.state or localStorage
            .page.len(loadTableLength()) // load from history.state or localStorage
            .page(page-1)
            .draw(false);
    });
});

Upvotes: 0

Related Questions