Salvo Salvo - 2 months ago 129
Javascript Question

Jquery Datatable gives error when recreating datatable: TypeError: t[c] is undefined

I have a function that creates a datatable. On page load the datatable is created and drawn. Now, when I have a form submit to make a search on a table, I call the same function. First I make an instance of the datatable, I call the clear function then I call the function to recreate it.

Here is how I create the datatable for the first time, which works just fine:

$(window).load(function () {


var table = UpdateTableCompany(null, null);
.....


Here is the function which manages the datatable:

function UpdateTableCompany(val, search_field)
{
$('#tablePubDev').DataTable().clear();
var table = $('#tablePubDev').DataTable({
destroy: true,
searching: false,
"lengthMenu": [[5, 10, 15, -1], [5, 10, 15, "All"]],
"pageLength": 5,
"columnDefs": [
{
"render": function (data, type, row) {


var text = '<div class="form-group">' +
'<div class="checkbox-nice center" style="cursor: default; height:100px;">' +
'<img src="/application/assets/img/pub_devs/logos/' + row['c']['logo'] + '" style="max-height:100%; max-width: 100%;"/>' +
'</div>' +
'<div class="checkbox-nice text-center" style="cursor: default">' +
'<strong >Id: ' + pad(data, 11) + '</strong>' +
'</label>' +
'</div>' +
'</div>';


return text;
},
"targets": 0,
},
{
"render": function (data, type, row) {


var text = '<div class="form-group">' +
'<div class="checkbox-nice center" style="cursor: default; height:100px;"><p class="center" style="font-size: 150%; font-weight: bold;">' +
row['c']['descr'] +
'</p></div>' +
'</div>';


return text;
},
"targets": 1,
},
{
"render": function (data, type, row) {

var add_text1 = '';
var checked1 = '';
var add_text2 = '';
var checked2 = '';

if (data != null && data > 0) {

checked1 += 'checked="checked"';
} else
add_text1 += 'buttonDisabled ';

if (row['c']['developer'] != null && row['c']['developer'] > 0) {

checked2 += 'checked="checked"';
} else
add_text2 += 'buttonDisabled ';


var text = '<div class="form-group">' +
'<div class="checkbox-nice ' + add_text1 + '" style="cursor: default">' +
'<input type="checkbox" ' + checked1 + ' disabled="disabled" id="checkbox-1">' +
'<label for="checkbox-1">' +
'Publisher ' +
'</label>' +
'</div>' +
'<div class="checkbox-nice ' + add_text2 + '" style="cursor: default">' +
'<input type="checkbox" id="checkbox-2" ' + checked2 + ' disabled="disabled">' +
'<label for="checkbox-2">' +
'Developer' +
'</label>' +
'</div>' +
'</div>';


return text;
},
"targets": 3,
},
{
"render": function (data, type, row) {
var text = '<td style="width: 20%;">' +
//'<a href="#" class="table-link">' +
//'<span class="fa-stack">' +
//'<i class="fa fa-square fa-stack-2x"></i>' +
//'<i class="fa fa-search-plus fa-stack-1x fa-inverse"></i>' +
//'</span>' +
//'</a>' +
'<a href="#" class="table-link updatePubDev" data-modal="modal-11">' +
'<span class="fa-stack">' +
'<i class="fa fa-square fa-stack-2x"></i>' +
'<i class="fa fa-pencil fa-stack-1x fa-inverse"></i>' +
'</span>' +
'</a>' +
'<span class="fa-stack table-link danger deletePubDev">' +
'<i class="fa fa-square fa-stack-2x"></i>' +
'<i class="fa fa-trash-o fa-stack-1x fa-inverse"></i>' +
'</span>' +
'</td>';


return text;
},
"targets": 4,
}
],
"columns": [
{"data": "c.idpubdev", "name": "c.idpubdev"},
{"data": "c.descr", "name": "c.descr"},
{"data": "c.date_founded", "name": "c.date_founded"},
{"data": "c.publisher", "name": "c.publisher"},
{"data": "c.date_founded", "name": "c.date_founded"},
{"data": "c.developer", "name": "c.developer", "visible": false, "searchable": false},
{"data": "c.logo", "name": "c.logo", "visible": false, "searchable": false},

],
"order": [[0, false], [1, 'asc'], [2, 'asc'], [3, 'asc']],

"displayLength": 3,
serverSide: true,
"ajax":
{
"url": "/pubdev/search/",
"type": "POST",
"data": function (d) {
if (val)
d.val = val;
if (search_field)
d.search_field = search_field;
}

},
error: function (request, status, error) {
alert('Unable to update table contents');
console.log(request);
console.log(status);
console.log(error);
},

});

return table;
}


Here instead is the submit of the form which executes the search function:

$("#search_form").submit(function (e) {
e.preventDefault();

var search_key = $.trim($('#val').val());
var search_field = 'c.descr like ';

table = $('#tablePubDev').DataTable();

table.clear();

table = UpdateTableCompany(search_field, search_key);

});


I am currently using the minified format of jquery version v1.10.2
The version of datatable is 1.10.4

This is the error I get in the console
enter image description here

I tried an experiment: I did not load the datatable in document ready, so I made a search submit to load the datatable , and it worked! Of course if I do a second search then the same error occurs, so the problem has to do with the recreation of datatable. All the back end code (php) works correctly and gives the desired results.

Here is the table in html



<div class="main-box no-header clearfix">
<div class="main-box-body clearfix">
<div class="table-responsive">
<table id="tablePubDev" class="table user-list table-hover">
<thead>
<tr>
<th>Company</th>
<th>Name</th>
<th><span>Listed Games</th>
<th>Type</th>
<th>Actions</th>
</tr>
</thead>
<tbody>

</tbody>
</table>
</div>
</div>
</div>





I have tried using the unminified version of datatable (v 1.10.12) and I got still and error but now it says his:


TypeError: headerCells[i] is undefined

headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !==...



// Clone the table header and footer - we can't use the header / footer
// from the cloned table, since if scrolling is active, the table's
// real header and footer are contained in different table tags
tmpTable.find('thead, tfoot').remove();
tmpTable
.append( $(oSettings.nTHead).clone() )
.append( $(oSettings.nTFoot).clone() );

// Remove any assigned widths from the footer (from scrolling)
tmpTable.find('tfoot th, tfoot td').css('width', '');

// Apply custom sizing to the cloned header
**headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0]** ); <-- This is where the error occurs <--

for ( i=0 ; i<visibleColumns.length ; i++ ) {
column = columns[ visibleColumns[i] ];

headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
_fnStringToCss( column.sWidthOrig ) :
'';

// For scrollX we need to force the column width otherwise the
// browser will collapse it. If this width is smaller than the
// width the column requires, then it will have no effect
if ( column.sWidthOrig && scrollX ) {
$( headerCells[i] ).append( $('<div/>').css( {
width: column.sWidthOrig,
margin: 0,
padding: 0,
border: 0,
height: 1
} ) );
}
}

// Find the widest cell for each column and put it


UPDATE:

I think I know why this is happening, although I still need to find a fix for this. It just so happens that When I define my columns in the Datatable instantiation:

"columns": [
{"data": "c.idpubdev", "name": "c.idpubdev"},
{"data": "c.descr", "name": "c.descr"},
{"data": "c.date_founded", "name": "c.date_founded"},
{"data": "c.publisher", "name": "c.publisher"},
{"data": "c.date_founded", "name": "c.date_founded"},
{"data": "c.developer", "name": "c.developer", "visible": false, "searchable": false},
{"data": "c.logo", "name": "c.logo", "visible": false, "searchable": false},


These need to be exactly as many as the table headers that I included in my html page



<thead>
<tr>
<th>Company</th>
<th>Name</th>
<th><span>Listed Games</th>
<th>Type</th>
<th>Actions</th>
</tr>
</thead>





In this case I have 5 table headers and 7 data column definitions (two have visible = false). When I used them in an older project, all I had to do was set the "visible" property to false so that they wouldn't be mapped to a table header, but here it doesn't seem to work... Why do you think that would happen? I sthere a way to work around it?

Answer

Ok, I actually solved this problem! So there is a bug (feature ?? ) in the datatable.js plugin. When it tries to autowidth the columns, it needs to have as many headers as there are data columns defined. So if you have 7 column definitions and you have only 5 headers defined, the code will fail with a null pointer exception. One way to work around this is to set the autowidth parameter to false (by default it is true).

   function UpdateTableCompany(val, search_field)
    {

        var table = $('#tablePubDev').DataTable({
            'destroy': true,
            searching: false,
            'info': false,
            paging: true,
            retrieve: false,
            processing: true,
            "autoWidth": false, // This parameter must be set to false
          ......

By doing this you avoid the call to the functon which actually tries to do the autowidth. So by avoiding that part of the datatable code, you wont have the error described.

Comments