I have a page with two bootstrap tabs, each tab contains one datatable. The below behavior started occurring only after I integrated fixedColumns into both datatables.
On page load the first table is displayed correctly and fixedColumns works correctly. When I click on the tab for table 2 then the table is displayed, but the page content which should be below the table is displayed on top of the table, and fixedColumns does not work.
Table 1:
Table 2:
Link to the snippet, though I am having a difficult time getting it to render anything.
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>
Everything seems to be fine. The only thing is that following event listener of tab change is not working like as you mentioned in the comment.
//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();
});
});
It is because you are rendering that html content dynamically and at that point of time a[data-toggle="tab"]
element is not available. Better to place that code after you rendered the tabs and tables.
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();
});
});
});
});