I am building a hobby web-page using Bootstrap 5.3.3 and JS DataTables 2.0.5. On the page, I have a table with some players data. In the table i made it so when clicking on some cells a popover is shown with extra info. All the required modules are there and popover is working fine when table is shown at full width. However, if i adjust screen size so some of the columns become collapsed, the popover is not showing for those columns.
Repro example in JS Fiddle:
<head>
<meta charset="utf-8">
<title>Responsive Table Popover</title>
<meta name="description" content="">
<meta name="author" content="">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="https://cdn.datatables.net/2.0.5/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/responsive/3.0.2/css/responsive.bootstrap5.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<table id="players-data" class="table table-striped" style="font-size:13px; width: 100%;">
<thead style="white-space: nowrap;">
<tr>
<th>Player</th>
<th>Details 1</th>
<th>Details 2</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"> </script>
<script charset="utf8" src="https://cdn.datatables.net/2.0.5/js/dataTables.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/2.0.5/js/dataTables.bootstrap5.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/responsive/3.0.2/js/dataTables.responsive.min.js"></script>
<script charset="utf8" src="https://cdn.datatables.net/responsive/3.0.2/js/responsive.bootstrap5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<script type="text/javascript">
let players = [
{player: 'Best', details_1: 'Cool', details_2: 'Sharp', details_1_extra: 'Extra Cool', details_2_extra: 'Extra Sharp'},
{player: 'Worst', details_1: 'Hot', details_2: 'Slow', details_1_extra: 'Extra Hot', details_2_extra: 'Extra Slow'}
];
$('#players-data').DataTable({
data: players,
columns: [
{data: 'player', render: DataTable.render.text(), sortable: true},
{data: 'details_1', sortable: false, class: "text-center", render: function (data, type, row) {
if (data)
{
return `<a
tabindex="0"
type="button"
class="btn btn-link btn-sm"
data-bs-container="body"
data-bs-trigger="focus"
data-bs-toggle="popover"
data-bs-placement="bottom"
data-bs-html="true"
data-bs-custom-class="custom-popover"
data-bs-content="${row.details_1_extra}">
${data}
</a>`;
} else {
return data;
}
}},
{data: 'details_2', sortable: false, class: "text-center", render: function (data, type, row) {
if (data)
{
return `<a
tabindex="0"
type="button"
class="btn btn-link btn-sm"
data-bs-container="body"
data-bs-trigger="focus"
data-bs-toggle="popover"
data-bs-placement="bottom"
data-bs-html="true"
data-bs-custom-class="custom-popover"
data-bs-content="${row.details_2_extra}">
${data}
</a>`;
} else {
return data;
}
}}
],
destroy: true,
searching: false,
paging: true,
info: false,
ordering: true,
stateSave: true,
responsive: true,
drawCallback: function (settings) {
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));
}
});
</script>
</body>
When table is full width (all columns are shown) popovers on both columns are working fine:
When "Details 2" column is collaplsed due to screen size, popover is no longer shown on it no matter if you click on cell text:
What am I missing here in my code to make popovers work no matter what?
2
Answers
You should make the table element a child of a div element that has a class "table-responsive", for example:
When datatable is resized, and when uncollapsing collapsed cells, datatable actually adds another row, which contains collapsed cells, but in ul/li/span element, i.e. it creates new DOM elements, which don’t have popover or any other listener attached.
example of newly added elements:
So, what you need to do is when uncollapsing hidden cells, i.e. when datatable adds those elements, find and initiate popover on those newly added elements.
This could be done by adding separate listener on the whole table, or more precisely on collapsing element which has
.dtr-control
class, and then, find newly added row (which is control’s parent’s next sibling with class.child
), and in it find all newly added popovers, and initiate them:demo: