Bootstrap 5 DataTables
Bootstrap 5 DataTables in AdminKit PRO: DataTables 3 with search, sorting, paging and the Responsive, Buttons, FixedHeader and Select extensions.
This plugin is only available in AdminKit PRO. Learn more.
Use DataTables when a table has more rows than fit on one screen. People can search the table, sort it by any column and page through it. Extensions add more: columns that fold away on small screens, copy and print buttons, a header that stays in view and rows you can select.
AdminKit PRO comes with DataTables 3 and its Bootstrap 5 styling. The template styles the tables for light and dark mode, so they look like the rest of the dashboard. DataTables 3 does not need jQuery: you turn a table into a data table with new DataTable().
Example
Start with a normal Bootstrap table with a <thead> and a <tbody>. Then pass the table, or a selector for it, to new DataTable(). Without options, the table gets a search field, sortable columns, a page length menu and a pager.
<table id="datatables-basic" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr><td>Tiger Nixon</td><td>System Architect</td><td>Edinburgh</td><td>61</td><td>2026/09/12</td><td>$320,800</td></tr>
<tr><td>Garrett Winters</td><td>Accountant</td><td>Tokyo</td><td>63</td><td>2026/09/25</td><td>$170,750</td></tr>
<tr><td>Ashton Cox</td><td>Junior Technical Author</td><td>San Francisco</td><td>66</td><td>2026/01/21</td><td>$86,000</td></tr>
<tr><td>Cedric Kelly</td><td>Senior Javascript Developer</td><td>Edinburgh</td><td>22</td><td>2026/07/15</td><td>$433,060</td></tr>
<tr><td>Airi Satou</td><td>Accountant</td><td>Tokyo</td><td>33</td><td>2026/01/14</td><td>$162,700</td></tr>
<tr><td>Brielle Williamson</td><td>Integration Specialist</td><td>New York</td><td>61</td><td>2026/08/21</td><td>$372,000</td></tr>
<tr><td>Herrod Chandler</td><td>Sales Assistant</td><td>San Francisco</td><td>59</td><td>2026/08/03</td><td>$137,500</td></tr>
<tr><td>Rhona Davidson</td><td>Integration Specialist</td><td>Tokyo</td><td>55</td><td>2026/04/27</td><td>$327,900</td></tr>
<tr><td>Colleen Hurst</td><td>Javascript Developer</td><td>San Francisco</td><td>39</td><td>2026/02/27</td><td>$205,500</td></tr>
<tr><td>Sonya Frost</td><td>Software Engineer</td><td>Edinburgh</td><td>23</td><td>2026/01/17</td><td>$103,600</td></tr>
<tr><td>Jena Gaines</td><td>Office Manager</td><td>London</td><td>30</td><td>2026/01/18</td><td>$90,560</td></tr>
<tr><td>Quinn Flynn</td><td>Support Lead</td><td>Edinburgh</td><td>22</td><td>2026/09/04</td><td>$342,000</td></tr>
</tbody>
</table>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-basic");
});
</script>Responsive
With responsive: true, columns that do not fit the width of the table are hidden. A button in the first cell of each row shows them in a row below. Make the window narrower to see it.
<table id="datatables-responsive" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr><td>Tiger Nixon</td><td>System Architect</td><td>Edinburgh</td><td>61</td><td>2026/09/12</td><td>$320,800</td></tr>
<tr><td>Garrett Winters</td><td>Accountant</td><td>Tokyo</td><td>63</td><td>2026/09/25</td><td>$170,750</td></tr>
<tr><td>Ashton Cox</td><td>Junior Technical Author</td><td>San Francisco</td><td>66</td><td>2026/01/21</td><td>$86,000</td></tr>
<tr><td>Cedric Kelly</td><td>Senior Javascript Developer</td><td>Edinburgh</td><td>22</td><td>2026/07/15</td><td>$433,060</td></tr>
<tr><td>Airi Satou</td><td>Accountant</td><td>Tokyo</td><td>33</td><td>2026/01/14</td><td>$162,700</td></tr>
<tr><td>Brielle Williamson</td><td>Integration Specialist</td><td>New York</td><td>61</td><td>2026/08/21</td><td>$372,000</td></tr>
</tbody>
</table>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-responsive", {
responsive: true
});
});
</script>Buttons
The Buttons extension adds buttons above the table. copy copies the rows to the clipboard and print opens a print view of the table. Place them with the layout option. In topStart, they take the place of the page length menu.
<table id="datatables-buttons" class="table table-striped" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr><td>Tiger Nixon</td><td>System Architect</td><td>Edinburgh</td><td>61</td><td>2026/09/12</td><td>$320,800</td></tr>
<tr><td>Garrett Winters</td><td>Accountant</td><td>Tokyo</td><td>63</td><td>2026/09/25</td><td>$170,750</td></tr>
<tr><td>Ashton Cox</td><td>Junior Technical Author</td><td>San Francisco</td><td>66</td><td>2026/01/21</td><td>$86,000</td></tr>
<tr><td>Cedric Kelly</td><td>Senior Javascript Developer</td><td>Edinburgh</td><td>22</td><td>2026/07/15</td><td>$433,060</td></tr>
<tr><td>Airi Satou</td><td>Accountant</td><td>Tokyo</td><td>33</td><td>2026/01/14</td><td>$162,700</td></tr>
<tr><td>Brielle Williamson</td><td>Integration Specialist</td><td>New York</td><td>61</td><td>2026/08/21</td><td>$372,000</td></tr>
</tbody>
</table>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-buttons", {
responsive: true,
layout: {
topStart: {
buttons: ["copy", "print"]
}
}
});
});
</script>Use it in your page
js/app.js includes DataTables, its Bootstrap 5 styling and the Buttons, Responsive, FixedHeader and Select extensions. It makes DataTables available as window.DataTable, so a page needs no script of its own besides app.js. The styles are part of css/app.css.
app.js is a module script, and the browser runs module scripts once the page has been parsed. Wrap your code in a DOMContentLoaded listener, so it runs after app.js. The demo pages of the template do the same:
<table id="datatables-orders" class="table table-striped" style="width:100%">
<thead>...</thead>
<tbody>...</tbody>
</table>
<script type="module" src="js/app.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-orders", {
responsive: true
});
});
</script>new DataTable() returns the DataTables API of the table. Use it to search, filter or redraw the table from your own code.
Options
These are the options the demo pages use. The DataTables reference lists all of them.
| Option | What it does | Demo |
|---|---|---|
responsive: true | Hides the columns that do not fit and shows them in a row below | Responsive |
layout: { topStart: { buttons: ["copy", "print"] } } | Copy and print buttons above the table | Buttons |
fixedHeader: true | Keeps the header in view while the page scrolls | Fixed header |
select: { style: "multi" } | A click selects or deselects a row | Multi selection |
pageLength: 25 | The number of rows on a page (10 by default) | Fixed header |
ajax: "tables-datatables-ajax.json" | Loads the rows from a URL | Ajax |
AdminKit keeps two defaults of DataTables 1 for every table: the "Show 10 entries" page length menu and the Previous and Next buttons of the pager.
Column search
To filter one column at a time, add a <tfoot> and put a control in each footer cell. The column search demo builds a select per column from the values in that column:
<table id="datatables-column-search-select-inputs" class="table table-striped" style="width:100%">
<thead>...</thead>
<tbody>...</tbody>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-column-search-select-inputs", {
initComplete: function(settings) {
new DataTable.Api(settings).columns().every(function() {
var column = this;
var select = document.createElement("select");
select.className = "form-control";
select.setAttribute("aria-label", "Filter " + column.header().textContent);
select.add(new Option(""));
column.footer().replaceChildren(select);
select.addEventListener("change", function() {
var value = DataTable.util.escapeRegex(select.value);
column
.search(value ? "^" + value + "$" : "", true, false)
.draw();
});
column.data().unique().sort().each(function(value) {
select.add(new Option(value));
});
});
}
});
});
</script>Rows from a URL
When the rows come from a file or an API, pass its URL as ajax. The file holds the rows in a data array, one array per row in column order. That is how public/tables-datatables-ajax.json of the template stores them:
{
"data": [
["Airi Satou", "Accountant", "Tokyo", "33", "2026/01/14", "$162,700"]
]
}While the data loads, the table can show placeholder rows instead of an empty table. Mark the card body with aria-busy="true" and fill the <tbody> with Bootstrap placeholders. preDrawCallback keeps those rows until the data is in:
<div class="card-body" aria-busy="true">
<table id="datatables-ajax" class="table table-striped" style="width:100%">
<thead>...</thead>
<tbody class="placeholder-glow">
<tr aria-hidden="true">
<td><span class="placeholder col-8"></span></td>
<td><span class="placeholder col-10"></span></td>
<td><span class="placeholder col-6"></span></td>
<td><span class="placeholder col-4"></span></td>
<td><span class="placeholder col-7"></span></td>
<td><span class="placeholder col-6"></span></td>
</tr>
<!-- more placeholder rows -->
</tbody>
</table>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
new DataTable("#datatables-ajax", {
ajax: "tables-datatables-ajax.json",
// Keep the placeholder rows from the markup until the data is in,
// rather than drawing a "Loading..." row
preDrawCallback: function(settings) {
return settings.json !== undefined;
}
});
});
</script>When DataTables has drawn a table, app.js calls adminkit.ready() on it. That sets aria-busy="false" on the card body and removes any skeletons in it. While the card is busy, the info line and the pager keep their height, so the page does not move when the rows come in.
Styling
css/app.css includes the Bootstrap 5 stylesheets of DataTables and its four extensions. DataTables 3 is themed through CSS custom properties. AdminKit sets them in src/scss/5-vendor/_datatables.scss: selected rows get the primary color with white text. Everything else follows the Bootstrap table classes on the <table>, such as table-striped, in light and dark mode.
Accessibility
- Keep a
<thead>with a<th>per column, so screen readers announce the column of each cell. - DataTables labels its own search field and page length menu. Give the controls you add, such as column filters, a label or an
aria-label, as the select filters above do. - The placeholder rows have
aria-hidden="true", and the card body hasaria-busy="true"until the table is drawn.
Related
- React DataTables: the same tables in AdminKit for React
- Next.js DataTables: the same tables in AdminKit for Next.js
- Tables: Bootstrap's table classes without DataTables
- Placeholders: the loading rows of the Ajax example
- DataTables demo
Last updated on
Date picker
Bootstrap 5 datepicker with Vanilla Calendar Pro in AdminKit: an inline calendar, and in PRO a date, range and time picker that opens from an input.
CalendarPro
Bootstrap 5 FullCalendar in AdminKit PRO: FullCalendar 7 with month, week and day views, drag and drop events and color-coded event categories.