使用带有 Bootstrap 选项卡的 fixedColumns 的数据表问题

Datatables issue using fixedColumns with Bootstrap tabs

我有一个包含两个 bootstrap 选项卡的页面,每个选项卡包含一个数据table。以下行为仅在我将 fixedColumns 集成到两个 datatables.

后才开始发生

在页面加载时,第一个 table 正确显示并且 fixedColumns 正常工作。当我单击 table 2 的选项卡时,会显示 table,但应在 table 下方的页面内容显示在 table 之上,并且fixedColumns 不起作用。


Table 1:

Table 2:


Link to the snippet,虽然我很难让它渲染任何东西。

Javascript:

$(function () {
dataRetrievalpromise()
    .then(function (result) {
        generateTabsPromise(result)
            .then(function (result) {
                console.log(result);
                createTableHTMLPromise(result)
                    .then(function (result) {
                        createTableColumnsAndDataPromise(result);
                    });
            });
    });

//Below works only when debugging/using breakpoints
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
    //$('.dTable:visible').each(function (e) {

    //    $(this).DataTable().columns.adjust().responsive.recalc();

    //});
    $.fn.dataTable.tables({ visible: true, api: true })
    .columns.adjust()
    .fixedColumns().relayout()
    .responsive.recalc();
    //.fixedHeader.adjust();
    //.columns.adjust().redraw()
});
});


var generateTabsPromise = function (trainerJson) {
var promise = new Promise(function (resolve, reject) {
    var result = {};
    var tabInfo = [];
    var allMonthsFromJson = Object.getOwnPropertyNames(trainerJson);
    var tabHTML = '';
    for (var i = 0; i < allMonthsFromJson.length; i++) {
        tabInfo.push(allMonthsFromJson[i]);
    }
    for (var i = 0; i < tabInfo.length; i++) {
        //Make first tab active
        if (i == 0) {
            tabHTML += '<li class="active"><a href="' + '#tab-' + tabInfo[i] + '" data-toggle="tab"> ' + tabInfo[i] + '</a></li>';
        }
        else {
            tabHTML += '<li><a href="' + '#tab-' + tabInfo[i] + '" data-toggle="tab"> ' + tabInfo[i] + '</a></li>';
        }
    }
    $(".nav-tabs").html(tabHTML);
    result = { firstTab: tabInfo[0], jsonData: trainerJson, allMonthsInJson: allMonthsFromJson };
    resolve(result);
});
return promise;
};


function createTableHTMLPromise(generateTabsResult) {
var promise = new Promise(function (resolve, reject) {
    var tableHTML = '';
    for (var i = 0; i < generateTabsResult.allMonthsInJson.length; i++) {
        if (i === 0) {
            tableHTML += '<div class="tab-pane active" id="' + 'tab-' + generateTabsResult.allMonthsInJson[i] + '">';
            tableHTML += '<table class="table dTable" id="' + 'table-' + generateTabsResult.allMonthsInJson[i] + '" cellspacing="0" width="100%">' + '</table>';
            tableHTML += '</div>';
        }
        else {
            tableHTML += '<div class="tab-pane" id="' + 'tab-' + generateTabsResult.allMonthsInJson[i] + '">';
            tableHTML += '<table class="table dTable" id="' + 'table-' + generateTabsResult.allMonthsInJson[i] + '" cellspacing="0" width="100%">' + '</table>';
            tableHTML += '</div>';
        }
    }
    $(".tab-content").html(tableHTML);
    result = { allMonthsInJson: generateTabsResult.allMonthsInJson, jsonData: generateTabsResult.jsonData };
    resolve(result);
});
return promise;
}


function createTableColumnsAndDataPromise(createTableHTMLResult) {
var promise = new Promise(function (resolve, reject) {
    var result = {};
    var columnResult = [];
    for (var i = 0; i < createTableHTMLResult.allMonthsInJson.length; i++) {

        var month = createTableHTMLResult.jsonData[createTableHTMLResult.allMonthsInJson[i]].metaData.month;
        var numDays = createTableHTMLResult.jsonData[createTableHTMLResult.allMonthsInJson[i]].metaData.numDays;
        var year = createTableHTMLResult.jsonData[createTableHTMLResult.allMonthsInJson[i]].metaData.year;
        var tabName = createTableHTMLResult.allMonthsInJson[i];

        columnResult.push({ "data": "managerName", title: "managerName", "name": "managerName", "defaultContent": "" });
        columnResult.push({ "data": "employeeName", title: "employeeName", "name": "employeeName", "defaultContent": "" });

        for (var j = 0; j < numDays; j++) {
            if (j + 1 < 10) {
                columnResult.push({ "data": month + "-0" + String(j + 1) + "-" + year, title: month + "-" + String(j + 1) + "-" + year, "name": month + "-" + String(j + 1) + "-" + year, "defaultContent": "" });
            }
            else {
                columnResult.push({ "data": month + "-" + String(j + 1) + "-" + year, title: month + "-" + String(j + 1) + "-" + year, "name": month + "-" + String(j + 1) + "-" + year, "defaultContent": "" });
            }
        }
        initiateTable(columnResult, createTableHTMLResult.jsonData[tabName].data, tabName);
        columnResult = [];
        tabName = "";
    }
    resolve(result);
});
return promise;
}


function initiateTable(columnArray, tableData, tab) {
//console.log("initiateTable called: " + tab);
var table = $("#table-" + tab).DataTable({
    data: tableData,
    "columns": columnArray,
    "scrollX": true,
    scrollCollapse: true,
    "paging": false,
    "searching": false,
    "fixedColumns": {
        leftColumns: 2
    }
});
}

var dataRetrievalpromise = function () {
var jsonData = {};
var promise = new Promise(function (resolve, reject) {
    //console.log('first method completed ');
    resolve(jsonData = {
        "Jan-2019": {
            "metaData": {
                "month": "Jan",
                "numDays": 31,
                "year": "2019"
            },
            "data": [
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 1",
                    "Jan-01-2019": "<span style='background-color:green;'>Event 1</span>",
                    "Jan-03-2019": "Event #3"
                },
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 2",
                    "Jan-02-2019": "Event #2"
                },
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 3",
                    "Jan-01-2019": "Event #1"
                }
            ]
        },
        "Feb-2019": {
            "metaData": {
                "month": "Feb",
                "numDays": 28,
                "year": "2019"
            },
            "data": [
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 1",
                    "Feb-01-2019": "<span style='background-color:green;'>Event 1</span>",
                    "Feb-03-2019": "Event #3"
                },
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 2",
                    "Feb-06-2019": "Event #2"
                },
                {
                    "managerName": "Person 1",
                    "employeeName": "Employee 3",
                    "Feb-01-2019": "Event #1"
                }
            ]
        }
    });
});
return promise;
};

HTML:

<link href="~/Content/bootstrap.css" rel="stylesheet" />
<link href="~/Content/dataTables.bootstrap.css" rel="stylesheet" />
<link href="~/Content/fixedColumns.bootstrap.css" rel="stylesheet" />
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<div class="container">
    <div role="tabpanel">
       <ul class="nav nav-tabs"></ul>
       <div class="tab-content"></div>
    </div>
</div>
<script src="~/Scripts/bootstrap337.min.js"></script>
<script src="~/Scripts/jquery.dataTables.js"></script>
<script src="~/Scripts/dataTables.bootstrap.js"></script>
<script src="~/Scripts/dataTables.responsive.js"></script>
<script src="~/Scripts/dataTables.fixedColumns.js"></script>
<script src="~/Scripts/test2.js"></script>

一切似乎都很好。唯一的问题是标签更改的后续事件侦听器不像您在评论中提到的那样工作。

//Below works only when debugging/using breakpoints
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
  $.fn.dataTable.tables({ visible: true, api: true })
    .columns.adjust()
    .fixedColumns().relayout()
    .responsive.recalc();
  });
});

这是因为您正在动态呈现 html 内容,并且在那个时间点 a[data-toggle="tab"] 元素不可用。最好在呈现选项卡和表格后放置该代码。

dataRetrievalpromise().then(function (result) {
  generateTabsPromise(result).then(function (result) {
    createTableHTMLPromise(result).then(function (result) {
      createTableColumnsAndDataPromise(result);
      $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
        $.fn.dataTable.tables({ visible: true, api: true })
          .columns.adjust()
          .fixedColumns().relayout()
          .responsive.recalc();
      });
    });
  });
});

Demo