AdminKitDocs
Plugins

Bootstrap 5 DataTables

Bootstrap 5 DataTables in AdminKit PRO: DataTables 3 with search, sorting, paging and the Responsive, Buttons, FixedHeader and Select extensions.

Pro

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.

OptionWhat it doesDemo
responsive: trueHides the columns that do not fit and shows them in a row belowResponsive
layout: { topStart: { buttons: ["copy", "print"] } }Copy and print buttons above the tableButtons
fixedHeader: trueKeeps the header in view while the page scrollsFixed header
select: { style: "multi" }A click selects or deselects a rowMulti selection
pageLength: 25The number of rows on a page (10 by default)Fixed header
ajax: "tables-datatables-ajax.json"Loads the rows from a URLAjax

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.

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 has aria-busy="true" until the table is drawn.

Last updated on

On this page