AdminKitDocs
Plugins

React DataTables

React DataTables in AdminKit PRO: a DataTable component with Bootstrap 5 styling, search, sorting, paging and the Responsive, Buttons and Select extensions.

Pro

This component is only available in AdminKit PRO. Learn more.

Use DataTable when a table has more rows than fit on one screen. People can search it, 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.

DataTable is a React component around DataTables, built on its official React component, datatables.net-react. It loads the Bootstrap 5 styling of DataTables, so your tables look like the rest of AdminKit for React. It also loads four extensions: Buttons (with its HTML5 export and print buttons), Responsive, FixedHeader and Select.

DataTables is a large library, so the component loads it with React.lazy. Vite puts DataTables in its own chunk, a separate JavaScript file, and the browser only downloads it on a page that shows a DataTable. Until DataTables has drawn the table, a skeleton holds its place.

Example

Pass the rows as data, one columns entry per column, and the header as children. Write the column titles yourself in the <thead>. Leave title out of columns, or DataTables writes it over the header that React renders.

import { DataTable } from "@/components/plugins/datatable";

type Employee = {
  name: string;
  position: string;
  office: string;
  age: number;
  startDate: string;
  salary: string;
};

const employees: Employee[] = [
  { name: "Tiger Nixon", position: "System Architect", office: "Edinburgh", age: 61, startDate: "2026/09/12", salary: "$320,800" },
  { name: "Garrett Winters", position: "Accountant", office: "Tokyo", age: 63, startDate: "2026/09/25", salary: "$170,750" },
  { name: "Ashton Cox", position: "Junior Technical Author", office: "San Francisco", age: 66, startDate: "2026/01/21", salary: "$86,000" },
  { name: "Cedric Kelly", position: "Senior Javascript Developer", office: "Edinburgh", age: 22, startDate: "2026/07/15", salary: "$433,060" },
  { name: "Airi Satou", position: "Accountant", office: "Tokyo", age: 33, startDate: "2026/01/14", salary: "$162,700" },
  { name: "Brielle Williamson", position: "Integration Specialist", office: "New York", age: 61, startDate: "2026/08/21", salary: "$372,000" },
  { name: "Herrod Chandler", position: "Sales Assistant", office: "San Francisco", age: 59, startDate: "2026/08/03", salary: "$137,500" },
  { name: "Rhona Davidson", position: "Integration Specialist", office: "Tokyo", age: 55, startDate: "2026/04/27", salary: "$327,900" },
  { name: "Colleen Hurst", position: "Javascript Developer", office: "San Francisco", age: 39, startDate: "2026/02/27", salary: "$205,500" },
  { name: "Sonya Frost", position: "Software Engineer", office: "Edinburgh", age: 23, startDate: "2026/01/17", salary: "$103,600" },
  { name: "Jena Gaines", position: "Office Manager", office: "London", age: 30, startDate: "2026/01/18", salary: "$90,560" },
  { name: "Quinn Flynn", position: "Support Lead", office: "Edinburgh", age: 22, startDate: "2026/09/04", salary: "$342,000" },
];

const columns = [
  { data: "name" },
  { data: "position" },
  { data: "office" },
  { data: "age" },
  { data: "startDate" },
  { data: "salary" },
];

export function EmployeesTable() {
  return (
    <DataTable
      id="datatables-employees"
      className="table table-striped"
      data={employees}
      columns={columns}
      options={{ responsive: true }}
    >
      <thead>
        <tr>
          <th>Name</th>
          <th>Position</th>
          <th>Office</th>
          <th>Age</th>
          <th>Start date</th>
          <th>Salary</th>
        </tr>
      </thead>
    </DataTable>
  );
}

Props

DataTable takes the props of datatables.net-react. The component is in src/components/plugins/datatable.tsx.

PropTypeDefaultDescription
dataany[]The rows, as objects or arrays
columnsobject[]DataTables' column options, such as data
ajaxstring | objectA URL or Ajax configuration to load the rows from
optionsDataTableOptionsAny other DataTables option
classNamestringClasses for the <table>, such as table table-striped
idstringid of the <table>
childrenReactNodeThe <thead>, and Column elements for custom cells
refRef<DataTableRef>ref.current.dt() returns the DataTables API
on<Event>functionA DataTables event in camelCase, such as onInit or onSelect

The DataTableOptions and DataTableApi types are in src/components/plugins/datatable-helpers.ts, based on the types of datatables.net-react. AdminKit keeps two defaults of DataTables 1: the "Show 10 entries" length menu and the Previous and Next pager.

Extensions

To use an extension, turn it on in options, as the demo pages do:

OptionExtensionDemo
responsive: trueHides 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

The types of the Buttons extension leave out the layout feature, so cast the object:

import type { DataTableOptions } from "@/components/plugins/datatable-helpers";

const options = {
  responsive: true,
  layout: { topStart: { buttons: ["copy", "print"] } },
} as DataTableOptions;

Custom cells

Sometimes a cell needs more than text, such as a badge. For that, add a Column child per column instead of columns. Give the Column a function as its child: it gets the cell value and returns JSX. Wrap the function in rowCell from datatable-helpers.ts when it needs the whole row instead. The column keeps its data, which sorting and searching still use. This is how the orders table of the demo shows its badges:

import { Column, DataTable } from "@/components/plugins/datatable";
import { rowCell } from "@/components/plugins/datatable-helpers";
import { type Order, orders } from "@/mocks/orders";

<DataTable className="table table-striped" data={orders} options={{ responsive: true }}>
  <thead>
    <tr>
      <th>#</th>
      <th>Total</th>
      <th>Status</th>
    </tr>
  </thead>
  <Column data="id">{(id: string) => <strong>{id}</strong>}</Column>
  <Column data="total">
    {rowCell((order: Order) =>
      order.status === "Paid" ? order.total : <s>{order.total}</s>
    )}
  </Column>
  <Column data="status">
    {(status: string) => <span className="badge badge-success-light">{status}</span>}
  </Column>
</DataTable>

Ajax data

When the rows come from a file or an API, pass its URL as ajax. The table loads the rows when it starts. If each row is an array in column order, the columns need no data. That is how public/tables-datatables-ajax.json stores them: { "data": [["Airi Satou", "Accountant", ...]] }. For a file in public/, asset() from @/lib/site adds the base path of the app:

import { asset } from "@/lib/site";

<DataTable
  className="table table-striped"
  ajax={asset("/tables-datatables-ajax.json")}
  columns={[
    { footer: "Name" },
    { footer: "Position" },
    { footer: "Office" },
    { footer: "Age" },
    { footer: "Start date" },
    { footer: "Salary" },
  ]}
>
  <thead>...</thead>
</DataTable>

The DataTables API

To search, filter or redraw the table from your own code, use the DataTables API. onInit runs once the table has its data, and event.dt is the API. Later on, a ref gives you the same API through ref.current?.dt(). The column search demo uses it to filter a column:

<DataTable
  data={employees}
  columns={columns}
  onInit={(event: { dt: DataTableApi }) => {
    event.dt.column(2).search("Tokyo").draw();
  }}
>

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 select. Give the controls you add, such as column filters, a label or aria-label, as the select filters of the column search demo do.
  • The skeleton has aria-hidden="true". The table takes its place once DataTables has drawn it.

Last updated on

On this page