Dragos Dragos - 5 months ago 38
Javascript Question

DataTable child rows aren't showing up

I tried using the child rows feature from DataTables, but I'm doing something wrong, not sure what. (I'm new to DataTables)
I'm trying to add some static child rows, just to see it's working (no AJAX).
Clicking on the first column just adds the 'shown' class to the row, but no child row is added.

Also, no error is thrown.

I followed their example from here, removing the AJAX data.
I know it doesn't make any sense in my example (clicking an icon and showing the table from that link), but I just want to go in small steps.

This is what I've got for now:

HTML:

<table id='<%= league.name %>' class="event-table display responsive no-wrap">
<thead>
<tr>
<th class="event-badge"></th>
<th class="event-shirt"></th>
<th class="event-team"></th>
<th class="event-dash"></th>
<th class="event-team"></th>
<th class="event-shirt"></th>
<th class="event-badge"></th>
</tr>
</thead>
<tbody>
<% events.each do |event| %>
<tr class="event-row">
<td class="event-badge"><%= image_tag event.home_team.badge_url, :class => 'team-badge' %></td>
<td class="event-shirt"><%= image_tag event.home_team.shirt_url, :class => 'team-shirt' %></td>
<td class="event-team"><%= event.home_team.name %></td>
<td class="event-dash"> - </td>
<td class="event-team"><%= event.away_team.name %></td>
<td class="event-shirt"><%= image_tag event.away_team.shirt_url, :class => 'team-shirt' %></td>
<td class="event-badge"><%= image_tag event.away_team.badge_url, :class => 'team-badge' %></td>
</tr>
<% end %>
</tbody>
</table>


JS:

var table = $('.event-table').DataTable({
"bJQueryUI": true,
"bPaginate": false,
"bFilter": false,
"bInfo": false,
"columns": [
{
"className": "details-control",
"data": "badge-home"
},
{
"data": "shirt-home"
},
{
"data": "name-home"
},
{
"data": "dash"
},
{
"data": "name-away"
},
{
"data": "shirt-away"
},
{
"data": "badge-away"
}
]
});

$('.event-table tbody').on('click', 'td.details-control', function () {
var tr = $(this).closest('tr');
var row = table.row( tr );

if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format() ).show();
tr.addClass('shown');
}
} );

function format ( ) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
'<tr>'+
'<td>Full name:</td>'+
'<td>Something</td>'+
'</tr>'+
'<tr>'+
'<td>Extension number:</td>'+
'<td>Something</td>'+
'</tr>'+
'<tr>'+
'<td>Extra info:</td>'+
'<td>And any further details here (images etc)...</td>'+
'</tr>'+
'</table>';
}


UPDATE

I did not specify that I had multiple such tables on the same page. Only one was visible. The child rows are actually added but on the wrong table.
This fiddle shows the behaviour
How can I know what table to add the rows to?

Answer

You seem to be referring to the table object created by DataTables. However if you have multiple tables initialized by the same call, your table object will only refer to one of those tables (with unpredictable results). Your best bet is to store a reference on each of those table objects in the table data.

Rewrite the initialization part like so:

$(.event-table).each(function () { 
var table = $(this).DataTable({
    "bJQueryUI": true,
    "bPaginate": false,
    "bFilter": false,
    "bInfo": false,
    "columns": [
        {
            "className": "details-control",
            "data": "badge-home"
        },
        {
            "data": "shirt-home"
        },
        {
            "data": "name-home"
        },
        {
            "data": "dash"
        },
        {
            "data": "name-away"
        },
        {
            "data": "shirt-away"
        },
        {
            "data": "badge-away"
        }
    ]
});
$(this).data("dataTableObject", table);
});
$('.event-table tbody').on('click', 'td.details-control', function () {
    var table = $(this).closest(".event-table").data("dataTableObject");
    var tr = $(this).closest('tr');
    var row = table.row( tr );

    if ( row.child.isShown() ) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    }
    else {
        // Open this row
        row.child( format() ).show();
        tr.addClass('shown');
    }
} );

function format ( ) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
    '<tr>'+
    '<td>Full name:</td>'+
    '<td>Something</td>'+
    '</tr>'+
    '<tr>'+
    '<td>Extension number:</td>'+
    '<td>Something</td>'+
    '</tr>'+
    '<tr>'+
    '<td>Extra info:</td>'+
    '<td>And any further details here (images etc)...</td>'+
    '</tr>'+
    '</table>';
}

Example fiddle:

https://jsfiddle.net/u4nze1tf/1/

Comments