Sani Huttunen Sani Huttunen - 6 months ago 59
HTML Question

Why doesn't columns.render execute when DataTable().draw() is called?

I'm puzzled to why columns.render is not included in the execution pipeline of DataTable().draw().

An example:

HTML

<table id="data">
<thead>
<tr>
<th>TimeColumn</th>
<th>Column 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>123</td>
<td>234</td>
</tr>
<tr>
<td>345</td>
<td>456</td>
</tr>
<tr>
<td>567</td>
<td>678</td>
</tr>
</tbody>
</table>

<button id="refresh">Refreh</button>


jQuery

$(document).ready(function () {
$('#data').DataTable({
columnDefs: [{
targets: 0,
render: function(data, type, row, meta) {
return data + ' time:' + Date.now();
}
}]
});

$('#refresh').on('click', function() {
$('#data').DataTable().draw();
});
});


The expected result when clicking the
Refresh
button is that the time value should advance in the first column, but it doesn't.

The assigned render function is never called after initialization.

(jsFiddle of the example.)

Is there any workaround or do I have to dig into the code of DataTables?

Answer

Instead of destroying the datatable and repopulating it I ended up modifying jquery.datatables.js version 1.10.2.

The main issue is that the line 1935 in jquery.datatables.js checks if the row is already created:

if ( aoData.nTr === null )
{
  _fnCreateTr(oSettings, iDataIndex);
}

One option to remedy this is to set aoData.nTr = null. But this might break other functionality or cause unwanted side effects so this is not an acceptable solution.

I opted to instead add an argument to the .draw() function (line 7137) and adding a setting called bForceReDraw (draw() already takes an argument so we add a second argument):

_api_register('draw()', function (resetPaging, forceReDraw) {
  return this.iterator( 'table', function ( settings ) {
    settings.bForceReDraw = forceReDraw === true;
      _fnReDraw(settings, resetPaging === false);
  } );
} );

Then I changed the null check on line 1935 to:

if ( aoData.nTr === null || oSettings.bForceReDraw === true )
{
  _fnCreateTr(oSettings, iDataIndex);
}

In the function _fnCreateTr() there is also a null check on nTr (line 1586) so I needed to modify that as well:

if ( row.nTr === null || oSettings.bForceReDraw === true )
{
  nTr = nTrIn || document.createElement('tr');
  ...

Now we simply call draw() with the new argument and everything works as expected.

$('#data').DataTable().columns.adjust().draw(false, true);
Comments