Datatables table loads twice, first time without table data
Datatables table loads twice, first time without table data
basejumper
Posts: 6Questions: 0Answers: 0
Hello! I'm having one strange thing with datatables table: it loads twice, first time for a very short period of time (less than one sec.) without data from database (showing message defined in sZeroRecords argument (Haven't found any record!) - looks like it tries to search for something and doesn't find it), second time it loads normally. Maybe my program tries to load table data before it loads Ajax source. I tried to put an alert within fnDrawCallback (alert(oSettings.aiDisplay.length);) ; it displays two times (firstly - 0 then - 47, correct table record count). It doesn't disturb me very much because within a second, maybe even less, correct data is being shown. I just want to know is it my personal error due to lack of knowledge or something more global. Help me please if you have any ideas about this issue. P.S. I'm using presently the last version of datatables (1.8.2). You can see my code below:
[code]
$(document).ready(function() {
$('#katalog').dataTable({
"fnDrawCallback": function ( oSettings ) {
alert(oSettings.aiDisplay.length);
/*Highlighting selected row*/
$('td').bind('mouseenter', function () { $(this).parent().children().each(function(){$(this).addClass('datatablerowhighlight');}); });
$('td').bind('mouseleave', function () { $(this).parent().children().each(function(){$(this).removeClass('datatablerowhighlight');}); });
/*Adding classes depending on sending state*/
$("tr:contains('waiting')").addClass ('waiting');
$("tr:contains('error')").addClass ('error');
$("tr:contains('cancelled')").addClass ('cancelled');
$('DIV.bottom').addClass('fg-button ui-widget-header ui-corner-bottom');
$('DIV.top').addClass('fg-button ui-widget-header ui-corner-top');
},
"bProcessing": false,
"bJQueryUI": true,
"oLanguage": {
"sLengthMenu": "_MENU_",
"sInfo": "Records from _START_ to _END_. Total: _TOTAL_ ",
"sZeroRecords": "Haven't found any record!",
"sInfoEmpty": "Empty table information!",
"sInfoFiltered": "Records filtred!",
"sSearch":"Search all columns:",
"oPaginate": {
"sFirst": "First",
"sPrevious": "Previous",
"sNext": "Next",
"sLast": "Last"
}
},
"sPaginationType": "full_numbers",
"sDom": '<"top"flpi<"clear">>rt<"bottom"lpi<"clear">>',
"bAutoWidth": true,
"sLengthMenu":"5,10,15",
"bServerSide": false,
"bStateSave": true,
"sAjaxSource": "getdata.php",
"aoData": [
/* check */{
"bSortable": false,
"bSearchable": false,
"sClass": "center"
},
/* status */{
"bSearchable": true,
"sClass": "center"
},
/* id */ {
"bSearchable": true,
"sClass": "center"
},
/* email */{
"bSearchable": true,
"sClass": "center"
}
]
});
});
[/code]
Server side code:
[code]
$dbQuery = "SELECT `id`, `email`, `status` FROM `addresses` WHERE `status` <> 'sent'";
$query = execQuery($dbQuery, "object");
$sOutput = '{';
$sOutput .= '"aaData": [ ';
while($result = $query->fetch_assoc()){
$sOutput .= "[";
$sOutput .= ($result["status"] == "error") ? '"",' : '"",';
$sOutput .= '"' . str_replace('"', '/"', $result["status"]) . '",';
$sOutput .= '"' . str_replace('"', '/"', $result["id"]) . '",';
$sOutput .= '"' . str_replace('"', '/"', $result["email"]) . '"';
$sOutput .= "],";
}
$sOutput = substr_replace($sOutput, "", -1);
$sOutput .= '] }';
echo $sOutput;
[/code]
[code]
$(document).ready(function() {
$('#katalog').dataTable({
"fnDrawCallback": function ( oSettings ) {
alert(oSettings.aiDisplay.length);
/*Highlighting selected row*/
$('td').bind('mouseenter', function () { $(this).parent().children().each(function(){$(this).addClass('datatablerowhighlight');}); });
$('td').bind('mouseleave', function () { $(this).parent().children().each(function(){$(this).removeClass('datatablerowhighlight');}); });
/*Adding classes depending on sending state*/
$("tr:contains('waiting')").addClass ('waiting');
$("tr:contains('error')").addClass ('error');
$("tr:contains('cancelled')").addClass ('cancelled');
$('DIV.bottom').addClass('fg-button ui-widget-header ui-corner-bottom');
$('DIV.top').addClass('fg-button ui-widget-header ui-corner-top');
},
"bProcessing": false,
"bJQueryUI": true,
"oLanguage": {
"sLengthMenu": "_MENU_",
"sInfo": "Records from _START_ to _END_. Total: _TOTAL_ ",
"sZeroRecords": "Haven't found any record!",
"sInfoEmpty": "Empty table information!",
"sInfoFiltered": "Records filtred!",
"sSearch":"Search all columns:",
"oPaginate": {
"sFirst": "First",
"sPrevious": "Previous",
"sNext": "Next",
"sLast": "Last"
}
},
"sPaginationType": "full_numbers",
"sDom": '<"top"flpi<"clear">>rt<"bottom"lpi<"clear">>',
"bAutoWidth": true,
"sLengthMenu":"5,10,15",
"bServerSide": false,
"bStateSave": true,
"sAjaxSource": "getdata.php",
"aoData": [
/* check */{
"bSortable": false,
"bSearchable": false,
"sClass": "center"
},
/* status */{
"bSearchable": true,
"sClass": "center"
},
/* id */ {
"bSearchable": true,
"sClass": "center"
},
/* email */{
"bSearchable": true,
"sClass": "center"
}
]
});
});
[/code]
Server side code:
[code]
$dbQuery = "SELECT `id`, `email`, `status` FROM `addresses` WHERE `status` <> 'sent'";
$query = execQuery($dbQuery, "object");
$sOutput = '{';
$sOutput .= '"aaData": [ ';
while($result = $query->fetch_assoc()){
$sOutput .= "[";
$sOutput .= ($result["status"] == "error") ? '"",' : '"",';
$sOutput .= '"' . str_replace('"', '/"', $result["status"]) . '",';
$sOutput .= '"' . str_replace('"', '/"', $result["id"]) . '",';
$sOutput .= '"' . str_replace('"', '/"', $result["email"]) . '"';
$sOutput .= "],";
}
$sOutput = substr_replace($sOutput, "", -1);
$sOutput .= '] }';
echo $sOutput;
[/code]
This discussion has been closed.
Replies
The way you've set up your caching is not necessary; just put the whole "var oTable = $('#katalog').dataTable({ ... })" block into the document ready function, and Bob's your uncle!
I wonder if the filter is getting triggered? The handler itself seems fine, but is it possible that it's getting fired somehow?
If you use Firebug or Developer Tools to monitor network activity, is there only one request for the data?
Then a second draw is done the data is loaded - hence two calls to fnDrawCallback.
If you want to make the call only once - when the table is fully done, then fnInitComplete is the one for you. Alternatively there is an internal market which can be used to check if you want to, but it is internal and thus subject to change (although not going to in 1.8.x...!).
Regards,
Allan
Old post I know, but ran into this myself with an ajax source. Building on some of the comments above, I used the finInitComplete call to set the the fnDrawCallback that way I know the datatable is initialized
Update:
Seems I got over zealous with the above, while the alert was executed on fnInitComplete, I later realized that subsequent redraws did not make the call and unfortunately was not able to find a syntax that would allow me to set the drawback function after initialization.
That might have worked in very old versions of DataTables, but it certainly won't in newer versions. The settings object is considered to be private and show never be written to unless you are very familiar with how DataTables works internally.
In this case I would suggest using the public API and add a
draw
event handler:Allan