javascript 具有不同列数的数据表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26480434/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 06:00:57  来源:igfitidea点击:

DataTables with different number of columns

javascriptjqueryajaxdatatables

提问by Bishan

I am loading data using ajax and generating column names dynamically in my DataTable. My DataTable has different number of columns, depending on the selection by user.(There is a drop-down list).

我正在使用 ajax 加载数据并在我的 DataTable 中动态生成列名。我的数据表有不同的列数,具体取决于用户的选择。(有一个下拉列表)。

For example, there are 2 options in drop-down list as Southern Provinceand Northern Province. Southern Provincetable has 4 columns and Northern Provincetable has 6 columns.

例如,下拉列表中有 2 个选项为Southern ProvinceNorthern Province南部省表有 4 列,北部省表有 6 列。

Scenario 1

场景一

First user select Southern Provincewhich has 4 columns. Then it generates table without no errors, But after that if user select Northern Provincewhich has 6 columns, table not generate and js console print error as below.

第一个用户选择有 4 列的南方省。然后它生成没有错误的表,但之后如果用户选择有 6 列的北部省,表不会生成并且 js 控制台打印错误如下。

Uncaught TypeError: Cannot read property 'style' of undefined jquery.dataTables.js:3828

Uncaught TypeError: Cannot read property 'style' of undefined jquery.dataTables.js:3828

Scenario 2

场景二

First user select Northern Provincewhich has 6 columns. Then it generates table without no errors, But after that if user select Southern Provincewhich has 4 columns, table not generate and js console print error as below.

第一个用户选择有 6 列的北部省。然后它生成没有错误的表,但之后如果用户选择有 4 列的南方省,表不会生成并且 js 控制台打印错误如下。

Uncaught TypeError: Cannot read property 'mData' of undefined jquery.dataTables.js:6122

Uncaught TypeError: Cannot read property 'mData' of undefined jquery.dataTables.js:6122

But if both table has same number of columns, both tables generate without errors.

但是,如果两个表的列数相同,则两个表都会生成而不会出错。

How can I solve this ?

我该如何解决这个问题?

Here is the JS Code

这是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" ] ]
        });
    };
});

回答by Ali Raza Bhayani

I faced the same issue when my updated data had different number of columnsthan the previous data. The recipe is really simple!In the scenario when there is a change in number of columns, Destroy functionworks in conjunction with $("#datatable").empty();. So before reloading data your code would contain following lines:

当我更新的数据的列数与以前的数据同时,我遇到了同样的问题。食谱真的很简单!列数发生变化的情况下,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

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
}

var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;

dataTableObject = $('#myTable').DataTable({
        columns: columns,
        data:    data
    });

回答by davidkonrad

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 :

我认为最安全的方法是完全删除表,然后在重新初始化之前将其重新插入 DOM。在我看来,dataTables 没有完全删除所有生成的内容,这就是发生错误的原因(出于不同的原因)。从理论上讲,它或多或少应该像上面一样工作,但事实并非如此。考虑这个解决方案:

[full source in the demo link below]

[以下演示链接中的完整源代码]

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

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 aoColumnsfor different provinces and so on. And instead of relying on bDestroy, I remove the entire <table>with dataTable.fnDestroy(true)(both DOM andand dataTables injections) and then reinserts the <table>-skeleton before reinitialising the dataTable.

这有效。见demo -> http://jsfiddle.net/gss4a17t/基本上和OP中的一样,只是不同省份的功能不同,我aoColumns针对不同的省份做了不同的等等。而不是依靠bDestroy,我删除整个<table>dataTable.fnDestroy(true)(DOM都和数据表注射),然后重新插入<table>重新初始化数据表之前-skeleton。

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" :)

我不知道这是否适合 OP 的需要,但这就是我要做的。它对于未来的更改更加灵活,并且aoColumns-objects 可以从脚本自动生成或通过 AJAX 从服务器实现(例如,如果您想为不同的语言提供不同的标题)。“腰带和背带”:)

回答by parlad

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.

那里有很好的解决方案,但在遇到这个问题后,活力仍然在我脑海中响起。我想分享这个,而不是 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();
}

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

这里 d1, d2... 是你的 ajax 响应的关键。现在我们不必担心用户选择哪个值。注意:这不是这个问题的直接解决方案,而是比喻性的

回答by lgm

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.

我知道这是一个老问题,但由于我花了几个小时试图用 DataTables 1.10.18 解决它,所以我发布了它,希望它能对某人有所帮助。我使用 JavaScript 数组作为数据源,使用 jQuery 1.12.4。它基于@davidkonrad 的回答。

HTML:

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:

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

});