具有不同列数的数据表
Posted
技术标签:
【中文标题】具有不同列数的数据表【英文标题】:DataTables with different number of columns 【发布时间】:2014-12-16 07:23:41 【问题描述】:我正在使用 ajax 加载数据并在我的 DataTable 中动态生成列名。我的 DataTable 有不同的列数,具体取决于用户的选择。(有一个下拉列表)。
例如,下拉列表中有 Southern Province 和 Northern Province 两个选项。 Southern Province 表有 4 列,Northern Province 表有 6 列。
场景 1
第一个用户选择 Southern Province,它有 4 列。然后它会生成没有错误的表格,但是之后如果用户选择有6列的Northern Province,则不会生成表格并且js控制台打印错误如下。
Uncaught TypeError: Cannot read property 'style' of undefined jquery.dataTables.js:3828
场景 2
第一个用户选择 Northern Province,它有 6 列。然后它会生成没有错误的表格,但之后如果用户选择有4列的Southern Province,则表格不会生成并且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" ] ]
);
;
);
【问题讨论】:
制作小提琴并告诉我们 在调用 make_SP() 函数破坏数据表之前尝试一次。 @Gowri 我该怎么做?我用"bDestroy" : true
。但它不起作用。
@Bishan 一般要销毁表var table = $('#tabid').DataTable(); table.destroy();
@Gowri 尝试了您的解决方案并得到 js 错误为 Uncaught TypeError: Cannot read property 'aDataSort' of undefined jquery.dataTables.js:4160
【参考方案1】:
当我的更新数据与以前的数据相比列数不同时,我遇到了同样的问题。这个方法真的很简单!在列数发生变化的场景中,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
);
【讨论】:
我已将您的解决方案作为评论发布到datatables.net/manual/tech-notes/3#destroy。 (目前仍在等待审核)。 我刚才为我的一个项目解决这个问题的解决方案与这个非常相似,除了我无法检查它是否是一个数据表工作,所以我将它包装在<div id='tablewrapper'>
并检查了if (table.parent().attr('id') != 'tablewrapper')
。这种方法的好处是它不依赖于正在使用的数据表版本中的函数名称。【参考方案2】:
我认为最安全的方法是完全删除表,然后在重新初始化之前将其重新插入 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);
);
这行得通。查看演示 -> http://jsfiddle.net/gss4a17t/
基本上和OP里是一样的,只是我没有针对不同的省份有不同的功能,而是针对不同的省份做了不同的aoColumns
等等。而不是依赖bDestroy
,我用dataTable.fnDestroy(true)
(DOM 和和dataTables注入)删除了整个<table>
,然后在重新初始化dataTable之前重新插入<table>
-skeleton。
我不知道这是否适合 OP 的需要,但我会这样做。它对未来的更改更加灵活,aoColumns
-objects 可以从脚本自动生成或通过 AJAX 从服务器实现(例如,如果您想为不同的语言设置不同的标题)。 “腰带和背带”:)
【讨论】:
感谢您的回答。我没什么问题。我通过调用 url 获取数据。我如何将它与aaData
一起使用?
嘿@Bishan,感谢您的支持! :) 我认为应该是一样的,你从服务器获取的数据与我猜的小提琴中的 JSON 格式相同吗?然后获取数据,将结果插入为aaData
。因此,在 AJAX 的成功处理程序中调用“initDataTable”或任何您命名的名称。我无法在小提琴中重现这一点,但应该是这样的。
谢谢@davidkonrad,我用sAjaxSource
代替了aaData
。现在它正在工作。 :)【参考方案3】:
上面有很好的解决方案,但是在遇到这个问题之后,活力仍然在我脑海中敲响。我想分享这个,而不是 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 响应的关键。现在我们不必担心用户选择哪个值。注意:这不是这个问题的直接解决方案,而是比喻性的
【讨论】:
【参考方案4】:我知道这是一个老问题,但由于我花了几个小时试图用 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);
);
);
【讨论】:
以上是关于具有不同列数的数据表的主要内容,如果未能解决你的问题,请参考以下文章