Reputation: 147
following this tutorial I ended up with this code (that basically loads the child row content from an external file, parsed with JsRender, to an array) :
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
// carica il template del dettaglio
$.ajax ({
async: false,
type: "POST",
url: "incaricodetail.html",
cache: false,
success: function(data){
templateHtml = data;
}
});
var template = $.templates(templateHtml);
var htmlOutput = template.render(d);
return htmlOutput;
}
$(document).ready(function() {
$.fn.dataTable.moment( 'DD/MM/YYYY' );
var dettagli = [];
var table = $('#tabellaDati').DataTable( {
"data": <?= json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));?>,
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent":
'<a class="btn btn-xs" href="incarico_edit.php?id=<?=$id;?>&pageFrom=<?=pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME ); ?>" title="Modifica"><span class="glyphicon glyphicon-edit"></span></a>'+
'<a class="btn btn-xs delete-object" href="delete.php?id=<?=$row["id"]?>" delete-id="{$id}"" title="Elimina"><span class="glyphicon glyphicon-trash"></span></a>'+
'<a class="btn btn-xs" href="#" id="mostraDettaglio" title="dettaglio"><span class="glyphicon glyphicon-plus"></span></a>',
"render": function(data, type, row, meta) {
dettagli[meta.row] = format(data);
}
},
{ "data": "id" },
{ "data": "protocollo" },
{
"data": "dataIncarico",
"type": "date",
"dateFormat": "dd-mm-yyyy"
}
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing details
$('#tabellaDati tbody #mostraDettaglio').on('click', 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(dettagli[row.index()]).show();
tr.addClass('shown');
}
} );
} );
I don't know why, but the ajax call to the file incaricodetail.html is done three times (example, for two records I got 6 POST connections).
DataTables Debugger code: onucak
Whay could it be? Alex
Upvotes: 1
Views: 1074
Reputation: 85558
Upon initialization, render
is called on several occasions :
That is for each row! You can check the type of the render call through the type
argument. A qualified guess is that your render function is called on type
, display
and filter
- you have 2 rows, it gives 6 calls to the format()
function, and by that 6 POST connections since you have turned cache
off.
You can avoid that by simply :
render: function(data, type, row, meta) {
if (typeof dettagli[meta.row] == 'undefined') {
dettagli[meta.row] = format(data);
}
}
Why is render called multiple times with different type
?
So you can return different data for different purposes. Lets say you have some HTML containing a checkbox as display, for sort you can pass 0, for filtering you can pass yes / no, for type you can pass number.
Update. initialise dettagli[]
in initComplete()
instead of render()
:
var table = $('#example').DataTable({
initComplete : function() {
var api = this.api(),
rowCount = api.data().length;
for (var i=0;i<rowCount;i++) {
dettagli[i] = format(api.row(i).data()[0]);
}
}
});
This should do the same as dettagli[meta.row] = format(data);
, i.e call format()
with the content of column #0 for each row.
You should also consider loading incaricodetail.html
only once. Why load it over and over each time? It does not seem that the content of incaricodetail.html is meant to change, so would
var template;
$.get("incaricodetail.html", function(html) {
template = $.templates(html);
});
function format ( d ) {
return template.render(d);
}
not do exactly the same?
Upvotes: 1