Checkboxes and stateSave leads to reinitialise warning and does not work in auto refresh table

Checkboxes and stateSave leads to reinitialise warning and does not work in auto refresh table

xtlcxtlc Posts: 17Questions: 2Answers: 0

Being a total noob in js, I must say I love this project! I tried to implement an auto refresh table, which I was able to do in no time thanks to that great documentation, but now I am kind of stuck.
I want to have a checkbox in the column 0 (the one initialized with 0), I want a "check all" checkbox header and a must have is the preservation of the checked boxes after the setInterval function was executed. Note: Everything works fine Until adding checkboxes/stateSave, I am using this with Flask and bootstrap3.

I already tried to combine the answers from how to fix DataTables warning: table id=example - Cannot reinitialise DataTable and Cannot reinitialise DataTable and I am pretty sure I am not initializing my table multiple times (except from the setInterval function) and I also included "destroy: true" as suggested somwhere on the way. This should be working since 1.10.4 whereas I am using 1.10.20. I hope I did get my included files right, I also posted them here, as I saw in some forum posts this might cause an issue.

<!-- my includes: -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js"></script>
<script src="//cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs/dt-1.10.20/sl-1.3.1/datatables.min.css"/> 
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.3.1/css/select.dataTables.min.css"/> 

<script type="text/javascript" src="https://cdn.datatables.net/select/1.3.1/js/dataTables.select.min.js"></script> 
<script type="text/javascript" src="https://cdn.datatables.net/v/bs/dt-1.10.20/sl-1.3.1/datatables.min.js"></script> 
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.6.1/js/dataTables.buttons.min.js"></script> 

<script type="text/javascript">
$(document).ready( function () {        
    var table = $('#live_table').DataTable( {
        "ajax": {
            url: "/refreshLiveTableRoute",
            dataSrc: ""
        },
        destroy: true,      // destroy option
        stateSave: true,  // stateSave option
        columns: [
            { data: null, defaultContent: '' },
            { data: "status" },
            { data: "serial" }
        ],
        columnDefs: [ {
            orderable: true,
            className: 'select-checkbox',
            targets:   0
        } ],
        select: {
            style:    'os',
            selector: 'td:first-child'
        },
        order: [[ 1, 'asc' ]],        
    });
   
    setInterval( function () {
        table.ajax.reload( null, false ); // user paging is not reset on reload
    }, 1000 );
} );
</script>

This question has accepted answers - jump to:

Answers

  • colincolin Posts: 15,237Questions: 1Answers: 2,599

    Yep, as you say, that should work. I'm not familiar with Flask, so it might be something specific to that.

    If not, we're happy to take a look, but as per the forum rules, please link to a test case - a test case that replicates the issue will ensure you'll get a quick and accurate response. Information on how to create a test case (if you aren't able to link to the page you are working on) is available here.

    Cheers,

    Colin

  • xtlcxtlc Posts: 17Questions: 2Answers: 0
    edited April 2020

    Thanks for your help!
    I already installed the debugger and it gave me https://debug.datatables.net/elehew (Caution: I did remove a few columns for readability in my post).

    Is it correct that I let my flask return a json in this format:

    [
      {
        "id": 0, 
        "serial": "shelf-7f707767-00000000891a5abe", 
        "status": "<center><img src=\"/static/green.png\" width=\"10\" height=\"10\" title=\"status\"></center>"
      }, 
      {
        "id": 1, 
        "serial": "shelf-2344a7ad-00000000ffd3b527", 
        "status": "<center><img src=\"/static/yellow.png\" width=\"10\" height=\"10\" title=\"status\"></center>"
      }
    ]
    

    with an row "id" which I populate with ascending integers as values (this is the zero line in the columns)?

    Edit: I was able to fix the "reinitialise" error by reinstalling some libraries (dunno what exactly caused it, but I am fairly sure it was not datatables) - but I am still stuck with the problem that the checkboxes disappear every 1000ms (see my interval function).

  • kthorngrenkthorngren Posts: 21,170Questions: 26Answers: 4,922
    Answer ✓

    You are using the select extension to select the rows by clicking the checkbox. Datatables will automatically reselect the rows when using ajax.reload(). But it will only do so if there is a unique row identifier. Looks like you have id which might be unique, If it is try using rowId to set the rowId: "id" in your config options.

    Kevin

  • xtlcxtlc Posts: 17Questions: 2Answers: 0

    Thanks for that answer, that solved it.
    Clicking the datatables feels "clunky" - sometimes a click is disappearing right after the click, I would say 3 out of 10 times. Don't really know how to describe this behavior. I would think it is connected to that setInterval function. Do you have any idea what I could do to generate a more smooth experience? I am kind of reliant on quick updates (and I tried setting it to 3000ms and 5000ms which did not change that a lot).

  • colincolin Posts: 15,237Questions: 1Answers: 2,599

    Yep, I suspect it won't take the click between the initiation of the Ajax call and the draw - so that could be a significant portion of the time. Up it high, say to 30s and see if it's better - if it is, then you would need to consider which requirement is of the highest importance to you.

    Colin

  • kthorngrenkthorngren Posts: 21,170Questions: 26Answers: 4,922

    One way to make the experience better would be to replace ajax.reload() with a function that fetches the data via jQuery Ajax() then uses clear() to clear the table followed by rows.add() to add the rows. You will need to keep track of the selected rows and reselect them. There is still a time that clicking might feel clunky but it should be less as the ajax request is in the background.

    Kevin

  • xtlcxtlc Posts: 17Questions: 2Answers: 0

    @kthorngren that seems like a lot of work - I upped the time to 10 secs and see how the behavior is - for now.

  • kthorngrenkthorngren Posts: 21,170Questions: 26Answers: 4,922
    edited April 2020

    Wasn't too bad. See this example:
    http://live.datatables.net/zizenuga/1/edit

    It is still possible to click the button while the data is being updated and the click on work. Maybe its better, maybe its not.

    Kevin

  • xtlcxtlc Posts: 17Questions: 2Answers: 0

    I am afraid I did not get it :(

    I adapted your code:

    $(document).ready(function() {
    function getData() {
        $.ajax({
    
            url: "/refreshLiveTableRoute",
            dataSrc: "",
            success: function (data) {
    
            // Parse JSON string.
            data = JSON.parse(data);
    
            // Get Datatable API
            var table = $('#live_table').DataTable();
    
            // Get IDs of selected rows.
            var selected = table.rows({selected: true}).ids().toArray();
    
            // Add '#' to the IDs of each row
            selected.forEach(function(part, index) {
              this[index] = '#' + this[index];
            }, selected);
    
            console.log(selected)
    
            // Clear table.
            table.clear();
    
            // Add new row data, draw and stay on same page.
            table.rows.add(data.data).draw(false);
    
            // Reselect rows absed on ID.
            table.rows( selected ).select();
          }
        });
    }
    

    my call in comparison:

    $(document).ready( function () {        
        var events = $('#events');                  // from the get checkboxes
        var table = $('#live_table').DataTable( {
            "ajax": {
                url: "/refreshLiveTableRoute",
                dataSrc: ""
            },
            rowId: id, 
            stateSave: true, ... }});
    

    But in the console I only get: SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

    The content:

    [
      {
        "devices": "<img src=\"/static/tmp/display_black_3516.png\" width=\"30\" height=\"30\" title=\"3516\"> <img src=\"/static/tmp/display_black_ 3517.png\" width=\"30\" height=\"30\" title=\" 3517\">", 
        "id": 0, 
        "serial": "7f707767-0000000089a5abe", 
        "status": "<center><img src=\"/static/green.png\" width=\"10\" height=\"10\" title=\"status\"></center>""
      }, 
      {
        "devices": [], 
        "id": 1, 
        "serial": "2344a7ad-00000000ffdb527", 
        "status": "<center><img src=\"/static/yellow.png\" width=\"10\" height=\"10\" title=\"status\"></center>" "
      }
    ]
    

    My datatype did not chance, nor can I see any difference in how you call it to how I called it - could you please elaborate me?

  • kthorngrenkthorngren Posts: 21,170Questions: 26Answers: 4,922
    Answer ✓

    Line 6, dataSrc: "",, is a Datatables option. It can be removed as it is not doing anything for you.

    SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data

    Maybe you don't need line 10 data = JSON.parse(data);

    Line 29, table.rows.add(data.data).draw(false);, won't work for you since your data is not in the data object like my example. You need this instead:
    table.rows.add(data).draw(false);

    Kevin

  • xtlcxtlc Posts: 17Questions: 2Answers: 0
    edited April 2020

    Thanks for your time mate!! I had another error I was just able to save by myself :)

  • xtlcxtlc Posts: 17Questions: 2Answers: 0

    I just tried and I would say the clunkyness decreased by a lot. Thanks again!

This discussion has been closed.