Datatables With Different Number Of Columns
Solution 1:
I faced the same issue when my updated data had different number of columns than the previous data. The recipe is really simple! In the scenario when there is a change in number of columns, Destroy function
works in conjunction with $("#datatable").empty();
. So before reloading data your code would contain following lines:
if (dataTableObject) { // Check if DataTable has been previously created and therefore needs to be flushed
dataTableObject.fnDestroy(); // destroy the dataTableObject// For new version use table.destroy();
$('#' + DataTableDivID).empty(); // Empty the DOM element which contained DataTable// The line above is needed if number of columns change in the Data
}
// DataTable data loading/reloading codes comes here
So overall, your code may look like this:
if(dataTableObject) { // Check if table object exists and needs to be flushed
dataTableObject.fnDestroy(); // For new version use table.destroy();
$('#myTable').empty(); // empty in case the columns change
}
vardata = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTableObject = $('#myTable').DataTable({
columns: columns,
data: data
});
Solution 2:
I think the safest way is to remove the table completely, and then re-insert it to the DOM before reinitialising. Seems to me that dataTables not completely removes all generated content, thats why the error(s) occurs (for different reasons). In theory it should work as above, more or less, but it doesn't. Consider this solution :
[full source in the demo link below]
var dataTable,
domTable,
htmlTable = '<table id="example"><tbody></tbody></table>';
functioninitDataTable(province) {
if ($.fn.DataTable.fnIsDataTable(domTable)) {
dataTable.fnDestroy(true);
$('body').append(htmlTable);
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTable = $("#example").dataTable({
aaData : data,
aoColumns : columns
/* other options here */
});
domTable = document.getElementById('example');
}
$('#province-list').change(function() {
var prov = $(this).val();
initDataTable(prov);
});
This works. See demo -> http://jsfiddle.net/gss4a17t/
Basically it is the same as in OP, but instead of having different functions for different provinces, I have made different aoColumns
for different provinces and so on. And instead of relying on bDestroy
, I remove the entire <table>
with dataTable.fnDestroy(true)
(both DOM and and dataTables injections) and then reinserts the <table>
-skeleton before reinitialising the dataTable.
I dont know if that is adaptable to OP's need, but this is how I would do it. It is more flexible for future changes, and the aoColumns
-objects can be autogenerated from a script or achieved from the server by AJAX (if you want to have different titles for different languages, for example). "Belt and braces" :)
Solution 3:
There is good solution up there but after ran into this question, dynamism still ring the bell on my mind. i would like to share this , not a export in js. So please comment.
functiongenericAjaxCall(url, tableId, _header, _dataMapping, isData,
isEditDelete) {
if (!isData) {
$.ajax({
url : url,
method : "GET",
dataType : "JSON",
success : function(data) {
var editDeletUrl = url.split("/");
var dataArray = createArray(_header, data, _dataMapping, url,
isEditDelete)
createListHeading(tableId, dataArray, false);
initDT(tableId, dataArray);
},
error : function(xhr) {
console.log(xhr);
openErrorModal("Guru", xhr.responseText);
}
});
} else {
var dataArray = createArray(_header, url, _dataMapping);
console.log(dataArray);
var finalData = dataArray + objName;
console.log(finalData);
createListHeading(tableId, dataArray, false);
initDT(tableId, dataArray);
}
}
functioncreateArrayWithDelete(_header, data, _dataMapping, url) {
var posts = {};
posts.postDT = []
for (var i = 0; i < data.length; i++) {
var jsonData = {};
for (var j = 0; j < _header.length; j++) {
if (_dataMapping[j].indexOf('.') !== -1) {
var parts = _dataMapping[j].split(".");
if (String(data[i][parts[0]][parts[1]]).indexOf('*') !== -1) {
jsonData[_header[j]] = data[i][parts[0]][parts[1]].bold()
.replace("*", "");
} else {
jsonData[_header[j]] = data[i][parts[0]][parts[1]];
}
} else {
if (String(data[i][_dataMapping[j]]).indexOf('*') !== -1) {
jsonData[_header[j]] = data[i][_dataMapping[j]].bold()
.replace("*", "");
} else {
jsonData[_header[j]] = data[i][_dataMapping[j]];
}
}
}
if (_header[_header.length - 1]) {
jsonData["Action"] = deleteOnly(url,
data[i][_dataMapping[_dataMapping.length - 1]]);
}
posts.postDT.push(jsonData);
}
return posts.postDT;
}
functioncreateListHeading(tableId, data, isAction) {
var posts = {
post : []
};
$.each(data[0], function(key, value) {
posts.post.push({
"mDataProp" : key,
"sTitle" : key
/* "sType" : "string" */
});
});
cols = posts.post
}
functioninitDT(tableId, results) {
// Construct the measurement table
data_table = $('#' + tableId).DataTable({
"iDisplayLength" : 10,
scrollCollapse : true,
"aaSorting" : [],
"aaData" : results,
"aoColumns" : cols
});
$('#' + tableId).DataTable().columns.adjust();
}
And this is how i call ,
$(function() {
var header = [ "H1", "H2", "H3", "H4" ];
var dataMapping = [ "d1", "d2", "d3", "d3" ];
genericAjaxCall("ajaxurlWhichreturnJSON", "tableId", header, dataMapping,
false, true);
});
Here d1, d2... are the key of your ajax response. Now we do not need to worry that which value user select. Note : this is not direct solution of this question but it is figurative
Solution 4:
I know this is an old question, but since I spent several hours trying to solve it with DataTables 1.10.18, I publish it with the hope that it will help someone. I used JavaScript arrays as data source, and jQuery 1.12.4. It is based on @davidkonrad's answer.
HTML:
select province
<selectid="province-list"><optionvalue="sp">sp</option><optionvalue="np">np</option></select><br><br><divid="table-container"><tableid="example"class="display"></table></div>
JS:
var sp = [
[ 'col1', 'col2'] ,
[ 'col11', 'col22']
];
var np = [
[ 'col1', 'col2', 'col3', 'col4' ],
[ 'col11', 'col22', 'col33', 'col44' ]
];
var spColumns = [
{ title : "column1" },
{ title : "column2" }
];
var npColumns = [
{ title : "column1" },
{ title : "column2" },
{ title : "column3" },
{ title : "column4" }
];
var dataTable,
htmlTable = '<table id="example" class="display"></table>';
functioninitDataTable(province) {
if ($.fn.DataTable.isDataTable('#example')) {
dataTable = $('#example').DataTable();
dataTable.destroy(true);
$('#table-container').empty();
$('#table-container').append(htmlTable);
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTable = $('#example').DataTable( {
"data": data,
"columns": columns
} );
}
$(document).ready(function() {
initDataTable('sp');
$('#province-list').change(function() {
var prov = $(this).val();
initDataTable(prov);
});
});
Post a Comment for "Datatables With Different Number Of Columns"