Can I pass a DataTable object through jQuery's load() method?

Can I pass a DataTable object through jQuery's load() method?

Bob RodesBob Rodes Posts: 17Questions: 1Answers: 0
edited June 2016 in Free community support

I'm working on a dialog box with a DataTable in it. On the right, I have checkboxes. Here's the table code:

var theData = { "data": <?php echo $rs; ?> } 
for(var i=0;i<theData.data.length;i++)
  {
     theData.data[i].checkBox = '<input type=\"checkbox\">';
  }
 
var table = $('#example2').DataTable( {
    "data": theData.data,
    "columns": [
        {
            "className":      'details-control',
            "orderable":      false,
            "data":           null,
            "defaultContent": ''
        },
        { "data": "ID" },
        { "data": "CAGE" },
        { "data": "Name" },
        {
            'className': 'row-select',
            'orderable': false,
            'data': 'checkBox',
        }

    ],
    "order": [[1, 'asc']],
    paginate: false,
    scrollY: '375px',
    scrollCollapse: true,
} );

This is in a file called test3.php. I load this data as a jQuery UI modal dialog, so:

$("#test").on('click', function(e) {
    $("#dialog").load('test3.php', function() {
        $("#dialog").dialog({
            modal: true,
            width: '600px',
            position: {my:'top', at:'top+80'}
        });
    });
});

Now, what I'd like is to have access to the table object variable in the dialog context, so I can get at the values in the checkboxes. But it seems that all variables that are declared in the loaded file are out of scope. Now, load() allows you to pass an object parameter, but it has to be a plainObject, and DataTable() objects aren't. I've also tried attaching the object using $('#example2').data(table), and while the object is duly attached, it's also empty.

Now, I can create this monstrosity to iterate the checkbox values in the table from the dialog box context:

var theRows = 
$(this)[0].children[1].children[1].children[1].children[0].children[1].rows;
for(var i=0;i<theRows.length;i++) {
    console.log(theRows[i].children[4].children[0].checked);
}

...and avoid having to pass the table variable, but I'd like to be able to avail myself of the features of the variable. What's more, that solution doesn't appear very robust, as it assumes the internal structure of $(this) isn't subject to change in future versions of both jQuery UI and DataTables, which I rather doubt is an entirely safe assumption to make.

I've tried adding an argument to the dialog's load() method: load('test3.php', function(table) {etc.});, and then in test3.php putting return table; at the end, but it looks like the argument will only contain the entire contents of the loaded file in a string, no matter what you try to return. I thought of calling a function in test3.php from the load() method that would return a reference to the table object, but haven't been able to find any sort of syntax that works.

I've also tried storing the table variable with sessionStorage.setItem('theTable', table'), which provides me (upon calling sessionStorage.getItem('theTable')) with a forlorn little string: '[Object object]'. No joy there. I then tried packing the table variable with sessionStorage.setItem('theTable', JSON.stringify(table)); and unpacking it with JSON.parse(sessionStorage.getItem('theTable')), storing the result of the latter in a variable local to the dialog box. This at least provides me with a subset of the table object containing all the data, but it only takes a snapshot of the state of the table when it's opened, so it doesn't give me any way of looking at whether any boxes have been checked. None of this is really surprising, since the sessionStorage object is designed to store key/value pairs.

So. Is there a way to keep a reference to the table object in scope through the load() call, or do I have to use that piece of spaghetti code?

Replies

  • Bob RodesBob Rodes Posts: 17Questions: 1Answers: 0
    edited June 2016

    I used the "spaghetti code solution" above as a preliminary solution. However, I also ran into another problem: I have been putting ID values into an invisible column to access when I need to post changes or whatever, and invisible columns' data is also lost when you load the page.

    I was able to solve this by using jQuery's $.data() method, which allows you to attach key/value pairs to any DOM element. Two bits of code are required. First, in the loaded page's DataTable() options, use the rowCallback to tag each row with the desired data:

    'rowCallback': function(row, data, index) {
           $.data(row, 'ID', data.ID);
    }
    

    Then, using the theRows variable as defined in the "spaghetti code solution" above, access the ID like this: $(theRows[rowIndex]).data('ID'), where rowIndex is the index of the row you're trying to access.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    Now, what I'd like is to have access to the table object variable in the dialog context

    What you can do is call the DataTable constructor as many times as you want - but only on the first time can you pass options. When a table already exists and you call the constructor it will just return the DataTable object. So for example $('#myTable').DataTable() will return a DataTable API instance for #myTable no matter where you call it. That allows you to access it in any context.

    Regards,
    Allan

  • Bob RodesBob Rodes Posts: 17Questions: 1Answers: 0
    edited June 2016

    Ok. I tried using that and couldn't find my ID field, and assumed that it was because I had it as an invisible column in my table. As it turns out, it's there when I do this: $('#example2').DataTable().rows().data()[0].ID. I probably did something with mismatching case when I was trying that approach.

    What I still don't see is how to use the constructor to find out whether a checkbox has been checked or not. When I do this: $('#example2').DataTable().rows().data()[0].checkBox, where checkBox is the column name for a td containing the markup for a check box, I get the HTML itself rather than the object. If I do this: $(this)[0].children[1].children[1].children[1].children[0].children[1].children[4].children[0] I get the actual object and can evaluate its checked attribute.

    And then, I found https://editor.datatables.net/examples/api/checkbox.html and it looks like what I really didn't see is the DataTables way of doing checkboxes! Thanks Allan. Looks like I better rewrite that.

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin

    You could use:

    var td = table.cell(0, 0).node();
    var checked = $('input', td).is(':checked');
    

    which will get the first cell in the table (by row and data index - change the selector if needed) and then check for the checkbox state.

    But yes, Select has a built in checkbox option which can be useful.

    Allan

This discussion has been closed.