具有不同列数的DataTable

时间:2014-10-21 06:41:26

标签: javascript jquery ajax datatables

我正在使用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" ] ]
        });
    };
});

4 个答案:

答案 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);
  });

});