我正在使用ajax加载数据并在我的DataTable中动态生成列名。我的DataTable具有不同的列数,具体取决于用户的选择。(有一个下拉列表)。
例如,下拉列表中有2个选项为南方省和北方省。 南部省表有4列,北部省表有6列。
情景1
首先,用户选择南方省,其中包含4列。然后它生成表没有错误,但之后如果用户选择 Northern Province 有6列,表不生成和js控制台打印错误如下。
Uncaught TypeError: Cannot read property 'style' of undefined jquery.dataTables.js:3828
场景2
首先,用户选择 Northern Province ,其中包含6列。然后它生成表没有错误,但之后如果用户选择南方省有4列,表不生成和js控制台打印错误如下。
Uncaught TypeError: Cannot read property 'mData' of undefined jquery.dataTables.js:6122
但如果两个表的列数相同,则两个表都会生成错误。
我该如何解决这个问题?
这是JS代码
jQuery(document)
.ready(
function() {
$('#province-list').change(
function() {
var prov = $(this).val();
if (prov == "sp") {
make_SP();
} else if (prov == "np") {
make_NP();
}
});
function make_SP() {
$("#dataTables-res_item")
.dataTable(
{
"bDestroy" : true,
"bProcessing" : false,
"bServerSide" : true,
"sAjaxSource" : "/province_list_view?p_name=sp",
"aoColumns" : [
{
"mData" : "result_date",
"sTitle" : "Result Date"
},
{
"mData" : "result_day",
"sTitle" : "Result Day"
},
{
"mData" : "draw_number",
"sTitle" : "Draw Number"
},
{
"mData" : "draw_time",
"sTitle" : "Draw Time"
} ],
"order" : [ [ 0, "desc" ] ]
});
};
function make_NP() {
$("#dataTables-res_item")
.dataTable(
{
"bDestroy" : true,
"bProcessing" : false,
"bServerSide" : true,
"sAjaxSource" : "/province_list_view?p_name=np",
"aoColumns" : [
{
"mData" : "result_date",
"sTitle" : "Result Date"
},
{
"mData" : "result_day",
"sTitle" : "Result Day"
},
{
"mData" : "draw_number",
"sTitle" : "Draw Number"
},
{
"mData" : "draw_time",
"sTitle" : "Draw Time"
},
{
"mData" : "draw_place",
"sTitle" : "Draw Place"
},
{
"mData" : "draw_person",
"sTitle" : "Agent"
} ],
"order" : [ [ 0, "desc" ] ]
});
};
});
答案 0 :(得分:12)
当我的更新数据列数比以前的数据时,我遇到了同样的问题。配方非常简单!在列数更改的情况下,Destroy function
与$("#datatable").empty();
配合使用。因此,在重新加载数据之前,您的代码将包含以下行:
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
总体而言,您的代码可能如下所示:
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
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTableObject = $('#myTable').DataTable({
columns: columns,
data: data
});
答案 1 :(得分:11)
我认为最安全的方法是完全删除表,然后在重新初始化之前将其重新插入DOM。在我看来,dataTables没有完全删除所有生成的内容,这就是错误发生的原因(出于不同的原因)。从理论上讲,它应该或多或少地按照上述方式工作,但它并没有。考虑这个解决方案:
[以下演示链接中的完整资源]
var dataTable,
domTable,
htmlTable = '<table id="example"><tbody></tbody></table>';
function initDataTable(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);
});
这很有效。见demo - &gt;的 http://jsfiddle.net/gss4a17t/ 强>
基本上它与OP中的相同,但不是为不同的省份提供不同的功能,我为不同的省份制作了不同的aoColumns
,依此类推。我不是依赖bDestroy
,而是使用<table>
(DOM 和以及dataTables注入)删除整个dataTable.fnDestroy(true)
,然后重新插入<table>
-skeleton在重新初始化dataTable之前。
我不知道这是否适合OP的需要,但这就是我要做的。它对于将来的更改更加灵活,aoColumns
- 对象可以从脚本自动生成,也可以通过AJAX从服务器实现(例如,如果您希望为不同的语言使用不同的标题)。 &#34;腰带和牙套&#34; :)
答案 2 :(得分:0)
那里有一个很好的解决方案,但遇到这个问题后,活力仍然在我的脑海中震荡。我想分享这个,而不是在js中导出。所以请发表评论。
function genericAjaxCall(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);
}
}
function createArrayWithDelete(_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;
}
function createListHeading(tableId, data, isAction) {
var posts = {
post : []
};
$.each(data[0], function(key, value) {
posts.post.push({
"mDataProp" : key,
"sTitle" : key
/* "sType" : "string" */
});
});
cols = posts.post
}
function initDT(tableId, results) {
// Construct the measurement table
data_table = $('#' + tableId).DataTable({
"iDisplayLength" : 10,
scrollCollapse : true,
"aaSorting" : [],
"aaData" : results,
"aoColumns" : cols
});
$('#' + tableId).DataTable().columns.adjust();
}
这就是我所说的
$(function() {
var header = [ "H1", "H2", "H3", "H4" ];
var dataMapping = [ "d1", "d2", "d3", "d3" ];
genericAjaxCall("ajaxurlWhichreturnJSON", "tableId", header, dataMapping,
false, true);
});
这里d1,d2 ...是您的ajax响应的关键。现在,我们不必担心用户选择哪个值。注意:这不是此问题的直接解决方案,而是具有象征意义的
答案 3 :(得分:0)
我知道这是一个老问题,但是由于我花了几个小时尝试使用DataTables 1.10.18解决它,因此我发布了它,希望对大家有所帮助。我使用JavaScript数组作为数据源,并使用jQuery 1.12.4。它基于@davidkonrad的答案。
HTML:
select province
<select id="province-list">
<option value="sp">sp</option>
<option value="np">np</option>
</select>
<br><br>
<div id="table-container">
<table id="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>';
function initDataTable(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);
});
});