具有不同列数的DataTable
我正在使用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
第一个用户选择有6列的Northern Province 。 然后它生成表没有没有错误,但之后如果用户选择有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" ] ] }); }; });
我认为最安全的方法是完全删除表,然后在重新初始化之前将其重新插入DOM。 在我看来,dataTables没有完全删除所有生成的内容,这就是错误发生的原因(出于不同的原因)。 从理论上讲,它应该或多或少地起作用,但事实并非如此。 考虑这个解决方案
[以下演示链接中的完整源代码]
var dataTable, domTable, htmlTable = '
'; 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中的相同,但不是为不同的省份提供不同的function,我为不同的省份制作了不同的aoColumns
,依此类推。 而不是依赖于bDestroy
,我使用dataTable.fnDestroy(true)
(DOM和dataTables注入)删除整个
,然后在重新初始化dataTable之前重新插入
-skeleton。
我不知道这是否适合OP的需要,但这就是我要做的。 它对于将来的更改更加灵活, aoColumns
-objects可以从脚本自动生成,也可以通过AJAX从服务器实现(例如,如果你想为不同的语言设置不同的标题)。 “腰带和大括号”:)
当我的更新数据具有与先前数据不同的列数时,我遇到了同样的问题。 配方很简单! 在列数发生变化的情况下, Destroy function
与$("#datatable").empty();
一起使用$("#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 });
那里有很好的解决方案,但在遇到这个问题之后,动力仍然响起了我的脑海。 我想分享这个,而不是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响应的关键。 现在我们不需要担心用户选择哪个值。 注意:这不是这个问题的直接解决方案,但它具有象征意义