3

When a row is created, I would like to add a child row containing a <table>, for later population via on.click() + DataTable() + ajax. Pretty simple. The createdRow() callback seems like a great place to do this ... if I could get it to work.

createdRow() takes 4 parameters which appear to be the following.

  • row - HTML element of the created row
  • data - plain ol' JSON of the new row's data
  • dataIndex - the row # within its table
  • cells - DOM elements for the <td>s that make up the row

None of these are DataTables or child objects. Not only that, I do not seem to have a way to get at the underlying <table> element. Neither $(row).closest('table') nor $(cells[0]).closest('table') seem to return anything, and $(row).parent() doesn't work either. It seems as though the row isn't inserted into the table yet.

If the row really hasn't been inserted into the table when createdRow() is called, then I guess I just need to use another callback, like initComplete(), and iterate over rows. But createdRow() would be perfect, since all the data is right there in the args, so I hope I am just missing something simple and createdRow() can be made to work.

Thanks!

Bean Taxi
  • 1,104
  • 1
  • 9
  • 22

1 Answers1

3

You can access a table's API object from within the table itself using one of the approaches shown here. So, for example,

$('#your_table_id_here').DataTable()

With this, you can do the following to create a child row:

$('#example').DataTable( {
  "createdRow": function( row, data, dataIndex, cells ) {
    var myTable = $('#example').DataTable();
    myTable.row( dataIndex ).child( '<table><tr><td>some data</td></tr></table>' ).show();
  }
} );

This basically uses the row() API call with the row index number to get the row as a DataTables object (instead of a <tr> element).


If you are adding a new row via the DataTables API using row.add(), then you can use the row object which is returned from that function, without needing to create a new instance of the DataTable's API:

var row = table.row.add( ['John Doe', 'more info', ...] ).draw();
row.child( '<table><tr><td>some data</td></tr></table>' ).show();

The above example assumes that table is the variable assigned to your DataTable when the DataTable is created:

var table = $('#example').DataTable( {
   // your usual DataTable options here
} );

Adding a child to a row is typically done when the table is initially rendered, without using the createdRow option. I think this is the easiest way to handle things such as the open/close buttons (if you want those).


Update regarding a comment about not having access to the HTML table's ID.

Inside the createdRow callback function you can use this as a selector also: var myTable = $( this ).DataTable();. In this case, there is no need to know the ID of the table.

Using this, my earlier example becomes the following:

$('#example').DataTable( {
  "createdRow": function( row, data, dataIndex, cells ) {
    var myTable = $( this ).DataTable();
    myTable.row( dataIndex ).child( '<table><tr><td>some data</td></tr></table>' ).show();
  }
} );
andrewJames
  • 19,570
  • 8
  • 19
  • 51
  • Thank you, but I don't have a reference the table id within `createdRow()`. My initial page is a `
      ` of ``s, each of which gets turned into a DataTable during `$().ready()` and populated asynchronously via ajax. My plan was for `createdRow()` to add a child to each returned row in each returned table. Conceptually this is the best place to do it, as opposed to inside an `on.click()` handler as in the example you mentioned. I appreciate being pointed at workarounds, but in this case I'm really only interested in if it's possible in `createdRow()`. Thank you though.
    – Bean Taxi Mar 05 '21 at 18:26
  • Btw my current workaround is to loop over all the rows inside `initComplete()` callback, which isn't too bad. I'm unaccustomed to a callback on an object making it so difficult to refer to the source object, but perhaps that's just how it is in this case. – Bean Taxi Mar 05 '21 at 18:30
  • Understood. You should probably update your question with this extra information. In case it helps, you can use any valid jQuery selector in place of an `id` value - for example, you can use a class name common to all your tables: `var allMyTables = $('.some_class_name').DataTable();`. See [multiple tables](https://datatables.net/manual/api#Multiple-tables). That may or may not help you - it probably depends on the specific process by which your tables get turned into DataTables objects. – andrewJames Mar 05 '21 at 18:34
  • I added one more note to my answer - just in case it may also help (but I understand if it's not what you need). – andrewJames Mar 05 '21 at 21:23
  • The note did it :) `$(this)` was exactly what I was looking for. I knew there had to be something. Thanks! – Bean Taxi Mar 08 '21 at 21:44