Subscribe
5 October, 2026 8 min read Aigars Silkalns

AdminLTE 4 Data Tables: Tabulator, DataTables 3 Without jQuery, and Plain Bootstrap Tables

The best adminlte datatables — collage of six template screenshots

AdminLTE 3 shipped DataTables.net on top of jQuery; AdminLTE 4 ships neither. The v4 template dropped jQuery entirely, and its Data Tables demo page now runs on Tabulator, a vanilla-JavaScript grid with a Bootstrap 5 theme. That leaves three honest options for tables in an AdminLTE 4 project: Tabulator as the template does it, DataTables 3 — which no longer requires jQuery — for teams migrating from v3, or a plain Bootstrap table when the data is small enough not to need sorting and paging. This guide sets up all three inside a v4 card, with a global filter, header filters, export and dark mode, and every screenshot comes from a real page built on the starter template.

AdminLTE 4 card with a Tabulator data table: header filters, status badges and pagination

Which table library fits?

OptionjQueryBest forBootstrap 5 styling
Tabulator (what v4’s demo uses)NoNew v4 projects; header filters, editing, tree rows, virtual DOM for big dataOwn theme file (tabulator_bootstrap5.css)
DataTables 3No (from v3; v2 needed it)Teams porting v3 pages that already use the DataTables API and extensionsOfficial Bootstrap 5 integration package
Plain Bootstrap tableNoShort lists, settings pages, anything under a screenfulNative .table classes

All three are MIT-licensed. The deciding question is whether you need the DataTables extension ecosystem (Buttons, Responsive, Editor) or are starting fresh — in which case following the template’s own choice keeps you closest to what AdminLTE’s future demo pages and framework wrappers use.

Option 1: Tabulator, the way the v4 demo does it

Add Tabulator’s Bootstrap 5 theme to the head and its script after AdminLTE’s. The table mounts into an empty div, not a table element — Tabulator renders its own DOM:

<!-- head -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tabulator_bootstrap5.min.css">

<!-- after adminlte.min.js -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/tabulator.min.js"></script>
<div class="card">
  <div class="card-header">
    <h3 class="card-title">Users</h3>
    <div class="card-tools">
      <div class="input-group input-group-sm" style="width: 16rem">
        <span class="input-group-text"><i class="bi bi-search"></i></span>
        <input id="table-filter" type="search" class="form-control" placeholder="Filter rows…" aria-label="Filter rows">
      </div>
    </div>
  </div>
  <div class="card-body">
    <div class="d-flex gap-2 mb-3">
      <button id="export-csv" type="button" class="btn btn-sm btn-outline-secondary"><i class="bi bi-filetype-csv me-1"></i>Export CSV</button>
      <button id="export-json" type="button" class="btn btn-sm btn-outline-secondary"><i class="bi bi-filetype-json me-1"></i>Export JSON</button>
    </div>
    <div id="users-table"></div>
  </div>
</div>

The initialisation is the demo page’s, with a status column rendered as a Bootstrap badge through a formatter, a list-type header filter on Role and Status, and pagination:

const statusBadge = (cell) => {
  const map = { Active: 'success', Invited: 'info', Suspended: 'secondary' };
  return '<span class="badge text-bg-' + (map[cell.getValue()] || 'secondary') + '">' + cell.getValue() + '</span>';
};

document.addEventListener('DOMContentLoaded', () => {
  const data = [
    { id: 1, name: 'Olivia Bennett', email: '[email protected]', role: 'Admin',  status: 'Active',  joined: '2024-03-12' },
    { id: 2, name: 'Liam Carter',    email: '[email protected]',   role: 'Editor', status: 'Active',  joined: '2024-04-08' },
    // …
  ];

  const table = new Tabulator('#users-table', {
    data,
    layout: 'fitColumns',
    pagination: true,
    paginationSize: 10,
    paginationSizeSelector: [10, 25, 50],
    movableColumns: true,
    columns: [
      { title: '#', field: 'id', width: 60 },
      { title: 'Name', field: 'name', headerFilter: 'input' },
      { title: 'Email', field: 'email', headerFilter: 'input' },
      { title: 'Role', field: 'role', width: 120, headerFilter: 'list',
        headerFilterParams: { values: ['', 'Admin', 'Editor', 'Viewer'] } },
      { title: 'Status', field: 'status', width: 130, hozAlign: 'center', formatter: statusBadge,
        headerFilter: 'list', headerFilterParams: { values: ['', 'Active', 'Invited', 'Suspended'] } },
      { title: 'Joined', field: 'joined', width: 130, sorter: 'string' },
    ],
  });

  // Global filter box in the card header: match name OR email
  document.getElementById('table-filter').addEventListener('input', (e) => {
    const v = e.target.value;
    v ? table.setFilter([[{ field: 'name', type: 'like', value: v }, { field: 'email', type: 'like', value: v }]])
      : table.clearFilter();
  });

  // Export buttons
  document.getElementById('export-csv').addEventListener('click', () => table.download('csv', 'users.csv'));
  document.getElementById('export-json').addEventListener('click', () => table.download('json', 'users.json'));
});
AdminLTE 4 Tabulator table narrowed to three rows through the global search box

Two things the screenshots show that are easy to miss in the docs: header filters live in a second header row and combine with the global box, and layout: 'fitColumns' is what makes the grid fill the card on every viewport instead of scrolling horizontally. For server data, replace data with ajaxURL: '/api/users' and add paginationMode: 'remote' to let the server page and sort.

The v4 Data Tables page is this exact setup plus a print button — read its source when you want the template’s version rather than ours.

The AdminLTE 4 Data Tables demo page, powered by Tabulator

Option 2: DataTables 3 without jQuery

DataTables 2 still listed jQuery as a dependency; DataTables 3 removed it, so it now runs in an AdminLTE 4 page with nothing else loaded. Use the core package plus the Bootstrap 5 integration, which swaps the default styling for .table, .pagination and .form-control classes:

<!-- head -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/dataTables.bootstrap5.min.css">

<!-- after adminlte.min.js: core first, then the Bootstrap 5 integration -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/dataTables.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/js/dataTables.bootstrap5.min.js"></script>

Unlike Tabulator, DataTables enhances a real table element, which is the migration advantage: your v3 markup keeps working. The Bootstrap table classes stay on the element:

<div class="card">
  <div class="card-header">
    <h3 class="card-title">Users</h3>
  </div>
  <div class="card-body">
    <table id="users" class="table table-striped table-hover align-middle w-100">
      <thead>
        <tr><th>#</th><th>Name</th><th>Email</th><th>Role</th><th>Status</th><th>Joined</th></tr>
      </thead>
      <tbody>
        <tr><td>1</td><td>Olivia Bennett</td><td>[email protected]</td><td>Admin</td><td><span class="badge text-bg-success">Active</span></td><td>2024-03-12</td></tr>
        <!-- … -->
      </tbody>
    </table>
  </div>
</div>
document.addEventListener('DOMContentLoaded', () => {
  new DataTable('#users', {
    pageLength: 10,
    lengthMenu: [10, 25, 50],
    order: [[5, 'desc']],                    // newest first
    columnDefs: [{ targets: 0, width: '3rem' }],
    // where the controls go: length menu top-left, search top-right, info + paging below
    layout: { topStart: 'pageLength', topEnd: 'search', bottomStart: 'info', bottomEnd: 'paging' },
  });
});
AdminLTE 4 card with a DataTables 3 table styled by the Bootstrap 5 integration, no jQuery loaded

The new DataTable('#users', …) constructor replaces the old $('#users').DataTable() call; the options object is the same one you know, and the layout option replaces the old dom string for placing the search box and pager. Server-side processing is unchanged: ajax: '/api/users' with serverSide: true.

AdminLTE 4 DataTables 3 table filtered by the built-in search box

Dark mode needs no extra CSS. The Bootstrap 5 integration styles everything with Bootstrap variables, so data-bs-theme="dark" on the root element carries through the table, the search input and the pager:

AdminLTE 4 DataTables 3 table in dark color mode

Option 3: a plain Bootstrap table

Most admin tables are short. A settings page, a list of ten API keys, the last five logins — none of them need a library, and a plain table is faster, prints cleanly and has no JavaScript to break. AdminLTE 4’s Simple Tables page shows the useful combinations:

<div class="card">
  <div class="card-header"><h3 class="card-title">Recent logins</h3></div>
  <div class="card-body p-0">
    <div class="table-responsive">
      <table class="table table-striped table-hover align-middle mb-0">
        <thead>
          <tr><th>User</th><th>IP</th><th>When</th><th class="text-end">Status</th></tr>
        </thead>
        <tbody>
          <tr><td>Olivia Bennett</td><td>203.0.113.7</td><td>2 minutes ago</td><td class="text-end"><span class="badge text-bg-success">OK</span></td></tr>
        </tbody>
      </table>
    </div>
  </div>
</div>
  • .card-body.p-0 lets the table run edge to edge inside the card, which is how the demo pages do it.
  • .table-responsive scrolls horizontally on small screens instead of breaking the layout.
  • .table-sm condenses rows when density matters more than touch targets.
  • Sorting a short table client-side is a ten-line function on the header click — you do not need a grid for it.
The AdminLTE 4 Simple Tables demo page with plain Bootstrap tables

Choosing between them

Start with a plain table and reach for a library the moment you need paging, sorting across more than a screenful, or filtering. From there: Tabulator if the project is new and you want the template’s own path (and features like inline editing and tree rows later); DataTables 3 if you are migrating v3 pages or rely on its extensions. Do not load both — they solve the same problem, and the second one is dead weight in every page.

Frequently asked questions

Does AdminLTE 4 include DataTables?

No. AdminLTE 4 bundles no table plugin. Its Data Tables demo page uses Tabulator, a jQuery-free grid loaded from a CDN, and the template’s own CSS only styles plain Bootstrap tables. You add the library you want.

Can I use DataTables with AdminLTE 4 without jQuery?

Yes, with DataTables 3 or later: its package no longer depends on jQuery, and you initialise it with new DataTable(‘#id’, options). Pair it with the datatables.net-bs5 integration for Bootstrap 5 styling. DataTables 2 and earlier still need jQuery loaded first.

Why does the v4 demo use Tabulator instead of DataTables?

AdminLTE 4 removed jQuery from the template, and Tabulator is vanilla JavaScript that ships a Bootstrap 5 theme and covers filtering, sorting, paging, editing and export without extensions. DataTables only dropped its jQuery requirement in version 3, so it is now a valid alternative.

How do I add a search box to an AdminLTE 4 table?

With Tabulator, listen to an input and call table.setFilter() with the fields to match (the demo filters name and email together). With DataTables, the built-in search box is placed by the layout option (topEnd: ‘search’); with a plain table, filter the rows yourself by toggling a hidden class on each tr.

How do I load table data from an API?

Tabulator: set ajaxURL to your endpoint and, for large sets, paginationMode: ‘remote’ so the server pages and sorts. DataTables: set ajax to the endpoint and serverSide: true for the same behaviour. Both send the page, sort and search parameters for you.

Do the tables work in dark mode?

DataTables’ Bootstrap 5 integration and plain Bootstrap tables follow data-bs-theme automatically. Tabulator’s Bootstrap 5 theme handles most of it, but check your custom formatters — a hard-coded background colour in a cell will not switch.

Related reading: the AdminLTE 4 install guide for the page these cards sit in, AdminLTE 4 modals for the edit dialog behind a row’s button, and — if your stack is React — the shadcn/ui data table templates roundup for the TanStack Table route.

Aigars Silkalns
Aigars Silkalns

Frontend web developer and founder of AdminLTE, the most popular open-source admin dashboard template on GitHub with 45,000+ stars. Over 10 years of experience building web applications with Bootstrap, React, Vue, Angular, Tailwind CSS, and WordPress. Creator of Colorlib and DashboardPack.