KTUIKTUI
KTUIKTUI
ComponentsDocsStudio

Getting Started

IntroductionInstallationApproachThemingJavaScriptDark modeRTLReferencesChangelog - v1.1.1Metronic TemplatePopular

Components

AccordionAvatarAlertBadgeBreadcrumbButtonCardCheckboxCollapseDatatableDatepickerSoonDismissDrawerDropdownImage InputInputUpdateKbdLinkModalPaginationProgressRadio GroupReparentScrollableScrollspyUpdateScrolltoSelectSeparatorSkeletonStepperStickySwitchTabsTextareaTheme SwitchToastNewTooltipToggleToggle GroupToggle PasswordTooltip
©2025 KtUI. All rights reserved.
A project by Keenthemes
Docs
Tailwind DataTable

Tailwind DataTable

Tailwind DataTable component simplifies the creation of interactive data tables for web applications. With features like sorting, pagination, and customizable layouts, for managing and displaying large datasets from static table or remote API endpoints.

Examples

Basic Usage

Tailwind DataTable example that loads data from a local HTML table element and enables pagination and sorting features for the dataset

<div class="grid w-full space-y-5">
  <div class="kt-card">
    <div class="kt-card-header min-h-16">
      <input
        type="text"
        placeholder="Search..."
        class="kt-input sm:w-48"
        data-kt-datatable-search="#kt_datatable_basic"
      /><button type="button" class="kt-btn kt-btn-outline">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="lucide lucide-plus"
          aria-hidden="true"
        >
          <path d="M5 12h14"></path>
          <path d="M12 5v14"></path></svg
        >Add
      </button>
    </div>
    <div
      id="kt_datatable_basic"
      class="kt-card-table"
      data-kt-datatable="true"
      data-kt-datatable-page-size="5"
      data-kt-datatable-state-save="true"
    >
      <div class="kt-table-wrapper kt-scrollable">
        <table class="kt-table" data-kt-datatable-table="true">
          <thead>
            <tr>
              <th scope="col" class="w-30" data-kt-datatable-column="label">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Label</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-20" data-kt-datatable-column="method">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Method</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-24" data-kt-datatable-column="status">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Status</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th
                scope="col"
                class="w-24"
                data-kt-datatable-column="lastSession"
              >
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Last Session</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th
                scope="col"
                class="w-16"
                data-kt-datatable-column="actions"
              ></th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>Guy Hawkins</td>
              <td>Web</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>22 Jul 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Sales Dept</td>
              <td>SSH</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>18 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Sales Dept</td>
              <td>Kerberos</td>
              <td><span class="kt-badge kt-badge-primary">Verified</span></td>
              <td>15 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Legal Dept</td>
              <td>Token</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>30 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Finance Dept</td>
              <td>API Key</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>28 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Design Dept</td>
              <td>FIDO U2F</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>16 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Compliance Dept</td>
              <td>OpenID</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>11 Aug, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Alice Smith</td>
              <td>Biometric</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>19 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>HR Dept</td>
              <td>Basic auth</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>6 Aug, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Guy Hawkins</td>
              <td>Web</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>22 Jul 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Sales Dept</td>
              <td>SSH</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>18 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Sales Dept</td>
              <td>Kerberos</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>15 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>Legal Dept</td>
              <td>Token</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>30 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!--begin:pagination-->
      <div class="kt-datatable-toolbar">
        <div class="kt-datatable-length">
          Show<select
            class="kt-select kt-select-sm w-16"
            name="perpage"
            data-kt-datatable-size="true"
          ></select
          >per page
        </div>
        <div class="kt-datatable-info">
          <span data-kt-datatable-info="true"></span>
          <div
            class="kt-datatable-pagination"
            data-kt-datatable-pagination="true"
          ></div>
        </div>
      </div>
      <!--end:pagination-->
    </div>
  </div>
</div>

Remote Data Source

Tailwind DataTable example that loads data from a remote API endpoint and enables server-side pagination and sorting features for the dataset.

<div class="grid w-full space-y-5">
  <div class="kt-card">
    <div class="kt-card-header min-h-16">
      <input
        type="text"
        placeholder="Search..."
        class="kt-input sm:w-48"
        data-kt-datatable-search="#kt_datatable_remote_source"
      />
    </div>
    <div
      id="kt_datatable_remote_source"
      class="kt-card-table"
      data-kt-datatable-page-size="5"
      data-kt-datatable-state-save="true"
    >
      <div class="kt-table-wrapper kt-scrollable">
        <table class="kt-table" data-kt-datatable-table="true">
          <thead>
            <tr>
              <th scope="col" class="w-30" data-kt-datatable-column="label">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Label</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-20" data-kt-datatable-column="method">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Method</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-24" data-kt-datatable-column="status">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Status</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th
                scope="col"
                class="w-24"
                data-kt-datatable-column="lastSession"
              >
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Last Session</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-24" data-kt-datatable-column="ipAddress">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">IP Address</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
            </tr>
          </thead>
          <tbody></tbody>
        </table>
      </div>
      <!--begin:pagination-->
      <div class="kt-datatable-toolbar">
        <div class="kt-datatable-length">
          Show<select
            class="kt-select kt-select-sm w-16"
            name="perpage"
            data-kt-datatable-size="true"
          ></select
          >per page
        </div>
        <div class="kt-datatable-info">
          <span data-kt-datatable-info="true"></span>
          <div
            class="kt-datatable-pagination"
            data-kt-datatable-pagination="true"
          ></div>
        </div>
      </div>
      <!--end:pagination-->
    </div>
  </div>
</div>

Group Check

Tailwind DataTable example that enables group check features to easily select multiple table rows through a single checkbox.

<div class="grid w-full space-y-5">
  <div class="kt-card">
    <div class="kt-card-header min-h-16">
      <input
        type="text"
        placeholder="Search..."
        class="kt-input sm:w-48"
        data-kt-datatable-search="#kt_datatable_group_check"
      /><button type="button" class="kt-btn kt-btn-outline">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="24"
          height="24"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
          class="lucide lucide-plus"
          aria-hidden="true"
        >
          <path d="M5 12h14"></path>
          <path d="M12 5v14"></path></svg
        >Add
      </button>
    </div>
    <div
      id="kt_datatable_group_check"
      class="kt-card-table"
      data-kt-datatable="true"
      data-kt-datatable-page-size="5"
      data-kt-datatable-state-save="true"
    >
      <div class="kt-table-wrapper kt-scrollable">
        <table class="kt-table kt-table-border" data-kt-datatable-table="true">
          <thead>
            <tr>
              <th scope="col" class="w-5">
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-check="true"
                />
              </th>
              <th scope="col" class="w-30" data-kt-datatable-column="label">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Label</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-20" data-kt-datatable-column="method">
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Method</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th scope="col" class="w-24" data-kt-datatable-column="status">
                <span class="kt-table-col asc"
                  ><span class="kt-table-col-label">Status</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th
                scope="col"
                class="w-24"
                data-kt-datatable-column="lastSession"
              >
                <span class="kt-table-col"
                  ><span class="kt-table-col-label">Last Session</span
                  ><span class="kt-table-col-sort"></span
                ></span>
              </th>
              <th
                scope="col"
                class="w-16"
                data-kt-datatable-column="actions"
              ></th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="0"
                />
              </td>
              <td>Guy Hawkins</td>
              <td>Web</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>22 Jul 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="1"
                />
              </td>
              <td>Sales Dept</td>
              <td>SSH</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>18 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="2"
                />
              </td>
              <td>Sales Dept</td>
              <td>Kerberos</td>
              <td><span class="kt-badge kt-badge-primary">Verified</span></td>
              <td>15 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="3"
                />
              </td>
              <td>Legal Dept</td>
              <td>Token</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>30 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="4"
                />
              </td>
              <td>Finance Dept</td>
              <td>API Key</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>28 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="5"
                />
              </td>
              <td>Design Dept</td>
              <td>FIDO U2F</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>16 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="6"
                />
              </td>
              <td>Compliance Dept</td>
              <td>OpenID</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>11 Aug, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="7"
                />
              </td>
              <td>Alice Smith</td>
              <td>Biometric</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>19 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="8"
                />
              </td>
              <td>HR Dept</td>
              <td>Basic auth</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>6 Aug, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="9"
                />
              </td>
              <td>Guy Hawkins</td>
              <td>Web</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>22 Jul 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="10"
                />
              </td>
              <td>Sales Dept</td>
              <td>SSH</td>
              <td>
                <span class="kt-badge kt-badge-destructive">Rejected</span>
              </td>
              <td>18 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="11"
                />
              </td>
              <td>Sales Dept</td>
              <td>Kerberos</td>
              <td><span class="kt-badge kt-badge-success">Approved</span></td>
              <td>15 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
            <tr>
              <td>
                <input
                  type="checkbox"
                  class="kt-checkbox"
                  data-kt-datatable-row-check="true"
                  value="12"
                />
              </td>
              <td>Legal Dept</td>
              <td>Token</td>
              <td><span class="kt-badge kt-badge-warning">Pending</span></td>
              <td>30 Jul, 2024</td>
              <td class="text-end">
                <span class="inline-flex gap-2.5"
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-pencil"
                      aria-hidden="true"
                    >
                      <path
                        d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"
                      ></path>
                      <path d="m15 5 4 4"></path></svg></a
                  ><a
                    href="#"
                    class="kt-btn kt-btn-sm kt-btn-icon kt-btn-outline"
                    ><svg
                      xmlns="http://www.w3.org/2000/svg"
                      width="24"
                      height="24"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      stroke-width="2"
                      stroke-linecap="round"
                      stroke-linejoin="round"
                      class="lucide lucide-trash"
                      aria-hidden="true"
                    >
                      <path d="M3 6h18"></path>
                      <path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
                      <path
                        d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
                      ></path></svg></a
                ></span>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!--begin:pagination-->
      <div class="kt-datatable-toolbar">
        <div class="kt-datatable-length">
          Show<select
            class="kt-select kt-select-sm w-16"
            name="perpage"
            data-kt-datatable-size="true"
          ></select
          >per page
        </div>
        <div class="kt-datatable-info">
          <span data-kt-datatable-info="true"></span>
          <div
            class="kt-datatable-pagination"
            data-kt-datatable-pagination="true"
          ></div>
        </div>
      </div>
      <!--end:pagination-->
    </div>
  </div>
</div>

How It Works

The DataTable component handles data display, sorting, pagination, and search for both local HTML tables and remote API endpoints.

Component Architecture

  • Core Component (KTDataTable class) - Manages the complete lifecycle including initialization, configuration, state management, and DOM manipulation
  • Checkbox Handler - Dedicated module for group selection and row checkbox management
  • Sort Handler - Handles column sorting for both local and remote data sources
  • Event System - Pub/sub pattern for lifecycle hooks and user interactions
  • State Management - Persistent state storage via localStorage for pagination, sorting, and selection

Data Flow

The component automatically detects and handles two distinct data modes:

Local Mode (Client-Side)

HTML Table → Extract Data → Apply Search → Apply Sort → Paginate → Render

Remote Mode (Server-Side)

API Request → Fetch Data → Transform (mapResponse) → Render → Update Pagination

Data Modes

The component automatically detects whether to use local or remote mode based on your configuration.

Local Data Mode

When to Use:

  • Static data from HTML tables
  • Small to medium datasets (< 1000 rows)
  • Client-side filtering and sorting requirements
  • No server-side API available

How It Works: When no apiEndpoint is configured, the component operates in local mode:

  1. Reads data from existing HTML <tbody> rows
  2. Stores original data in component state
  3. Applies all pagination, sorting, and search client-side
  4. Re-renders filtered/sorted data back to the DOM

Example:

<div data-kt-datatable="true" data-kt-datatable-page-size="10">
  <table class="kt-table" data-kt-datatable-table="true">
    <thead>
      <tr>
        <th data-kt-datatable-column="name">
          <span class="kt-table-col">
            <span class="kt-table-col-label">Name</span>
            <span class="kt-table-col-sort"></span>
          </span>
        </th>
        <!-- more columns -->
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>John Doe</td>
        <!-- more cells -->
      </tr>
      <!-- more rows -->
    </tbody>
  </table>
</div>

Performance Considerations:

  • Initial load reads all data from DOM (one-time operation)
  • Filtering and sorting operate on in-memory arrays (fast)
  • Re-rendering limited to visible page (efficient)
  • State persistence adds minimal overhead via localStorage

Remote Data Mode

When to Use:

  • Large datasets (> 1000 rows)
  • Server-side pagination, filtering, and sorting
  • Dynamic data that changes frequently
  • RESTful API integration

How It Works: When apiEndpoint is configured, the component operates in remote mode:

  1. Makes HTTP requests to the API endpoint
  2. Sends pagination, sort, and search parameters
  3. Receives paginated data and total count
  4. Renders only the current page
  5. Updates pagination controls based on total count

Example:

const datatable = new KTDataTable(element, {
  apiEndpoint: 'https://api.example.com/data',
  requestMethod: 'GET',
  requestHeaders: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token123'
  },
  requestCredentials: 'include', // Include cookies for session-based auth
  pageSize: 20,
 
  // Transform API response if needed
  mapResponse: (response) => ({
    data: response.items,
    totalCount: response.total
  })
});

API Request Parameters: The component automatically sends these query parameters:

  • page - Current page number (1-based)
  • size - Number of records per page
  • sortField - Column name to sort by (when sorting active)
  • sortOrder - Sort direction (asc, desc, or empty string)
  • search - Search query string or JSON object (when search active)
  • filters - JSON string of column filters (when filters active)

Expected API Response Format:

{
  "data": [
    { "id": 1, "name": "John", "email": "john@example.com" },
    { "id": 2, "name": "Jane", "email": "jane@example.com" }
  ],
  "totalCount": 150
}

Credentials Configuration

The requestCredentials option controls whether cookies, authorization headers, or TLS client certificates are included with fetch requests. This is essential for APIs that use session-based authentication.

Available Values:

  • "omit" - Never include credentials in requests
  • "same-origin" - Include credentials only for same-origin requests (browser default)
  • "include" - Always include credentials, even for cross-origin requests

Session-Based Authentication Example:

const datatable = new KTDataTable(element, {
  apiEndpoint: 'https://api.example.com/data',
  requestCredentials: 'include', // Send cookies for session auth
  requestHeaders: {
    'Content-Type': 'application/json'
  }
});

Cross-Origin Security Requirements: When using requestCredentials: 'include' with cross-origin APIs, the server must:

  • Set Access-Control-Allow-Credentials: true header
  • Specify the exact origin in Access-Control-Allow-Origin header (wildcard * is not permitted)

For more information, see the MDN Fetch API credentials documentation.

Mode Detection

The component automatically detects the mode - no manual configuration required:

// Local mode (no apiEndpoint)
const localTable = new KTDataTable(element, {
  pageSize: 10,
  stateSave: true
});
 
// Remote mode (apiEndpoint provided)
const remoteTable = new KTDataTable(element, {
  apiEndpoint: '/api/data',
  pageSize: 10
});

You cannot manually switch modes after initialization. If you need to change the data source, dispose of the current instance and create a new one.

Local Data Guide

Use local mode for small to medium datasets where client-side operations are sufficient.

Using HTML Tables

Provide data directly in your HTML markup. The component extracts and manages it automatically.

<div data-kt-datatable="true" data-kt-datatable-page-size="5">
  <table class="kt-table" data-kt-datatable-table="true">
    <thead>
      <tr>
        <th data-kt-datatable-column="name">
          <span class="kt-table-col">
            <span class="kt-table-col-label">Name</span>
            <span class="kt-table-col-sort"></span>
          </span>
        </th>
        <th data-kt-datatable-column="email">
          <span class="kt-table-col">
            <span class="kt-table-col-label">Email</span>
            <span class="kt-table-col-sort"></span>
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>John Doe</td>
        <td>john@example.com</td>
      </tr>
      <tr>
        <td>Jane Smith</td>
        <td>jane@example.com</td>
      </tr>
    </tbody>
  </table>
</div>

The component will:

  1. Extract data from each <tr> in the <tbody>
  2. Map each <td> to the corresponding column based on order
  3. Apply pagination, showing only 5 rows per page
  4. Enable sorting on columns with data-kt-datatable-column

Client-Side Behavior

In local mode, all operations happen in the browser:

Pagination:

  • Original data stored in memory
  • Only current page rendered in DOM
  • Fast navigation between pages
  • No server requests

Sorting:

  • Uses default alphanumeric sort
  • Can provide custom sort.callback for complex sorting
  • Instant sorting response
  • State persisted across page reloads

Search/Filtering:

  • Filters data array client-side
  • Uses default substring matching
  • Can provide custom search.callback for advanced filtering
  • Results update with configurable delay (default 500ms)

Custom Local Sorting

Provide a custom sort callback for specialized sorting logic:

const datatable = new KTDataTable(element, {
  pageSize: 10,
  sort: {
    callback: (data, sortField, sortOrder) => {
      return data.sort((a, b) => {
        const aValue = a[sortField];
        const bValue = b[sortField];
 
        // Numeric sorting
        if (typeof aValue === 'number') {
          return sortOrder === 'asc' ? aValue - bValue : bValue - aValue;
        }
 
        // Date sorting
        if (!isNaN(Date.parse(aValue))) {
          const dateA = new Date(aValue);
          const dateB = new Date(bValue);
          return sortOrder === 'asc'
            ? dateA - dateB
            : dateB - dateA;
        }
 
        // Default string sorting
        return sortOrder === 'asc'
          ? String(aValue).localeCompare(String(bValue))
          : String(bValue).localeCompare(String(aValue));
      });
    }
  }
});

Custom Local Search

Implement custom search logic for advanced filtering:

const datatable = new KTDataTable(element, {
  search: {
    delay: 300, // Shorter delay for faster response
    callback: (data, searchQuery) => {
      const query = searchQuery.toLowerCase();
 
      return data.filter(item => {
        // Search across multiple fields
        return (
          item.name?.toLowerCase().includes(query) ||
          item.email?.toLowerCase().includes(query) ||
          item.department?.toLowerCase().includes(query)
        );
      });
    }
  }
});

Search Input Configuration

Connect a search input to the DataTable using the data-kt-datatable-search attribute:

<!-- Search input references the datatable container ID -->
<input
  type="text"
  placeholder="Search..."
  data-kt-datatable-search="#my_datatable"
/>
 
<!-- Datatable container must have matching ID -->
<div id="my_datatable" data-kt-datatable="true">
  <table class="kt-table" data-kt-datatable-table="true">
    <!-- table markup -->
  </table>
  <!-- pagination controls -->
</div>

The search will automatically:

  • Debounce input by 500ms (configurable via search.delay)
  • Filter data using the search.callback function (or default substring matching)
  • Reset to page 1 when search is applied
  • Persist search state when stateSave is enabled

Important: The data-kt-datatable-search value must be a CSS selector (starting with # for IDs) that matches the DataTable container element.

Performance Considerations

Best Practices:

  • Local mode suitable for up to ~1000 rows
  • Beyond 1000 rows, use remote mode
  • Enable state persistence for better UX
  • Use debounced search to reduce filtering overhead

Column Configuration

Customize how each column is displayed and behaves using the columns configuration object.

Basic Column Customization

Define custom rendering for specific columns:

const datatable = new KTDataTable(element, {
  columns: {
    status: {
      title: 'Status',
      render: (value, row, context) => {
        // Return HTML string
        const badgeClass = value === 'active' ? 'kt-badge-success' : 'kt-badge-destructive';
        return `<span class="kt-badge ${badgeClass}">${value}</span>`;
      }
    },
    actions: {
      render: (value, row, context) => {
        // Return HTML for action buttons
        return `
          <div class="flex gap-2">
            <button class="kt-btn kt-btn-sm" data-id="${row.id}">Edit</button>
            <button class="kt-btn kt-btn-sm kt-btn-destructive" data-id="${row.id}">Delete</button>
          </div>
        `;
      }
    }
  }
});

Render Function Signatures

The render callback receives three parameters and can return different types:

render: (
  cellData: any,           // Value of this cell
  rowData: object,         // Complete row data object
  context: KTDataTable     // DataTable instance
) => string | HTMLElement | DocumentFragment

Return Types:

HTML String (most common):

render: (value, row) => {
  return `<span class="text-primary">${value}</span>`;
}

⚠️ Security Warning: Be careful with user-generated content. Always sanitize HTML strings to prevent XSS attacks.

DOM Element:

render: (value, row) => {
  const span = document.createElement('span');
  span.className = 'kt-badge';
  span.textContent = value; // Automatically escapes content
  return span;
}

Document Fragment:

render: (value, row) => {
  const fragment = document.createDocumentFragment();
  const icon = document.createElement('i');
  icon.className = 'icon-check';
  const text = document.createTextNode(value);
  fragment.appendChild(icon);
  fragment.appendChild(text);
  return fragment;
}

CreatedCell Callback

For post-render cell manipulation, use createdCell:

const datatable = new KTDataTable(element, {
  columns: {
    email: {
      createdCell: (cell, cellData, rowData, row) => {
        // Add custom classes
        cell.classList.add('text-primary', 'font-medium');
 
        // Attach event listeners
        cell.addEventListener('click', () => {
          console.log('Email clicked:', cellData);
        });
 
        // Add data attributes
        cell.dataset.email = cellData;
 
        // Add tooltips or popovers
        cell.setAttribute('title', `Send email to ${cellData}`);
      }
    },
    actions: {
      createdCell: (cell, cellData, rowData, row) => {
        // Attach click handlers to action buttons
        const editBtn = cell.querySelector('[data-action="edit"]');
        const deleteBtn = cell.querySelector('[data-action="delete"]');
 
        editBtn?.addEventListener('click', () => {
          console.log('Edit row:', rowData.id);
        });
 
        deleteBtn?.addEventListener('click', () => {
          console.log('Delete row:', rowData.id);
        });
      }
    }
  }
});

Nested Object Fields

Access nested properties in your data:

// Data structure with nested objects
const data = [
  {
    id: 1,
    user: {
      name: 'John Doe',
      profile: {
        avatar: '/avatars/john.jpg'
      }
    },
    metadata: {
      createdAt: '2024-01-15'
    }
  }
];
 
// Column configuration
const datatable = new KTDataTable(element, {
  columns: {
    'user.name': {
      title: 'User Name',
      render: (value, row) => {
        // Access nested data through row object
        const avatarUrl = row.user?.profile?.avatar || '/default-avatar.jpg';
        return `
          <div class="flex items-center gap-2">
            <img src="${avatarUrl}" class="w-8 h-8 rounded-full" />
            <span>${value}</span>
          </div>
        `;
      }
    }
  }
});

Custom CSS Classes

Apply custom styling to cells:

const datatable = new KTDataTable(element, {
  columns: {
    priority: {
      render: (value) => value,
      createdCell: (cell, cellData) => {
        // Conditional styling based on value
        const colorClasses = {
          high: 'bg-red-50 text-red-700',
          medium: 'bg-yellow-50 text-yellow-700',
          low: 'bg-green-50 text-green-700'
        };
        cell.className = `px-3 py-1 rounded ${colorClasses[cellData] || ''}`;
      }
    }
  }
});

Advanced Configuration

Advanced configuration options for complex use cases.

API Response Transformation

Transform API responses to match the expected format:

const datatable = new KTDataTable(element, {
  apiEndpoint: '/api/users',
 
  mapResponse: (response) => {
    // Handle different API response formats
 
    // Case 1: Nested data structure
    if (response.result && response.result.items) {
      return {
        data: response.result.items,
        totalCount: response.result.pagination.total
      };
    }
 
    // Case 2: Data in meta object
    if (response.data && response.meta) {
      return {
        data: response.data,
        totalCount: response.meta.total_count
      };
    }
 
    // Case 3: Laravel pagination format
    if (response.data && response.last_page) {
      return {
        data: response.data,
        totalCount: response.total,
        page: response.current_page,
        pageSize: response.per_page,
        totalPages: response.last_page
      };
    }
 
    // Default format
    return {
      data: response.data || [],
      totalCount: response.totalCount || response.total || 0
    };
  }
});

API Request Customization

Customize query parameters sent to the API:

const datatable = new KTDataTable(element, {
  apiEndpoint: '/api/data',
 
  mapRequest: (params) => {
    // Rename parameters for your API
    const page = params.get('page');
    const size = params.get('size');
    const sortField = params.get('sortField');
    const sortOrder = params.get('sortOrder');
    const search = params.get('search');
 
    // Create new params object
    const newParams = new URLSearchParams();
 
    // Map to your API's parameter names
    newParams.set('pageNumber', page || '1');
    newParams.set('pageLimit', size || '10');
 
    if (sortField) {
      newParams.set('orderBy', sortField);
      newParams.set('orderDirection', sortOrder === 'asc' ? 'ascending' : 'descending');
    }
 
    if (search) {
      newParams.set('q', search);
    }
 
    // Add custom parameters
    newParams.set('includeDeleted', 'false');
    newParams.set('format', 'json');
 
    return newParams;
  }
});

Loading State Customization

Customize the loading indicator:

const datatable = new KTDataTable(element, {
  loading: {
    template: `
      <div class="flex flex-col items-center justify-center py-12">
        <div class="spinner-border animate-spin w-12 h-12 border-4 border-primary rounded-full border-t-transparent"></div>
        <p class="mt-4 text-gray-600">{content}</p>
      </div>
    `,
    content: 'Loading data, please wait...'
  }
});

Custom Selectors

Override default selectors (defaults shown):

const datatable = new KTDataTable(element, {
  attributes: {
    table: 'table[data-kt-datatable-table="true"]',
    info: '[data-kt-datatable-info="true"]',
    size: '[data-kt-datatable-size="true"]',
    pagination: '[data-kt-datatable-pagination="true"]',
    spinner: '[data-kt-datatable-spinner="true"]',
    check: '[data-kt-datatable-check="true"]',
    checkbox: '[data-kt-datatable-row-check="true"]'
  }
});

Complete Configuration Example

A comprehensive example with all available options:

const datatable = new KTDataTable(element, {
  // Remote data configuration
  apiEndpoint: 'https://api.example.com/users',
  requestMethod: 'GET',
  requestHeaders: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_TOKEN'
  },
 
  // Transform API response
  mapResponse: (response) => ({
    data: response.items,
    totalCount: response.total
  }),
 
  // Customize query parameters
  mapRequest: (params) => {
    params.set('include', 'profile,permissions');
    return params;
  },
 
  // Pagination settings
  pageSize: 20,
  pageSizes: [10, 20, 50, 100],
  pageMore: true,
  pageMoreLimit: 5,
 
  // State management
  stateSave: true,
  stateNamespace: 'users-datatable',
 
  // Column customization
  columns: {
    name: {
      title: 'Full Name',
      render: (value, row) => `
        <div class="flex items-center gap-2">
          <img src="${row.avatar}" class="w-8 h-8 rounded-full" />
          <span>${value}</span>
        </div>
      `
    },
    status: {
      render: (value) => {
        const badge = value === 'active' ? 'kt-badge-success' : 'kt-badge-destructive';
        return `<span class="kt-badge ${badge}">${value}</span>`;
      }
    },
    actions: {
      render: (value, row) => `
        <button class="kt-btn kt-btn-sm" data-id="${row.id}">Edit</button>
      `,
      createdCell: (cell, cellData, rowData) => {
        cell.querySelector('button')?.addEventListener('click', () => {
          console.log('Edit:', rowData);
        });
      }
    }
  },
 
  // Search configuration
  search: {
    delay: 300,
    callback: (data, query) => {
      return data.filter(item =>
        item.name.toLowerCase().includes(query.toLowerCase())
      );
    }
  },
 
  // Sort configuration
  sort: {
    classes: {
      base: 'kt-table-col',
      asc: 'asc',
      desc: 'desc'
    },
    callback: (data, field, order) => {
      return data.sort((a, b) => {
        const comparison = String(a[field]).localeCompare(String(b[field]));
        return order === 'asc' ? comparison : -comparison;
      });
    }
  },
 
  // Checkbox configuration
  checkbox: {
    checkedClass: 'bg-primary-50',
    preserveSelection: true
  },
 
  // Loading customization
  loading: {
    template: '<div class="spinner">{content}</div>',
    content: 'Loading...'
  },
 
  // Info template
  info: 'Showing {start} to {end} of {total} entries',
  infoEmpty: 'No data available',
 
  // Custom selectors (if needed)
  attributes: {
    table: '[data-kt-datatable-table]',
    info: '[data-kt-datatable-info]',
    size: '[data-kt-datatable-size]',
    pagination: '[data-kt-datatable-pagination]'
  }
});
 
// Attach event listeners
datatable.on('init', () => console.log('Initialized'));
datatable.on('fetched', () => console.log('Data fetched'));
datatable.on('sort', (event) => console.log('Sorted:', event.detail));

Components API

Options

These options allow you to set options for the datatable component during auto initialization.

OptionTypeDefaultDescription
Data Options
data-kt-datatable-state-savebooleantrueSaves the state of the DataTable (e.g., pagination, sorting) so it can be restored when the user returns to the page.
data-kt-datatable-page-sizenumber10Sets the number of records to display per page in the DataTable. This value can be customized as needed.
JavaScript Options
requestMethodenum"GET"Defines the HTTP request method to be used for data fetching.
requestHeadersobject{"Content-Type": "application/x-www-form-urlencoded"}Specifies the headers to be sent with the request. For more info, check JavaScript Request Headers .
requestCredentialsenum"same-origin" (browser default)Controls whether cookies, authorization headers, or TLS client certificates are included with requests. Values: "omit", "same-origin", or "include". See Credentials Configuration for details.
infostring"{start}-{end} of {total}"Template for displaying the current page information in the DataTable.
infoEmptystring"No records found"Message displayed when no records are found in the DataTable.
pageSizesarray[5, 10, 20, 30, 50]Defines the available page size options for the DataTable.
pageSizenumber10Sets the default number of records displayed per page.
pageMorebooleantrueDisplays a more pages ... indicator if the number of pages exceeds the pageMoreLimit value.
pageMoreLimitnumber3Sets the threshold for displaying the "more pages" indicator.
paginationobjectsee codePagination options for controlling the DataTable navigation.
sortobjectsee codeSorting options for configuring how DataTable columns are sorted.
searchobjectsee codeSearching options for configuring how DataTable columns are filtered when searching.
loadingobjectsee codeLoading options to manage the DataTable loading state.
attributesobjectsee codeSpecifies the selectors for the elements to be targeted.
stateSavebooleantrueEnables saving the state of the DataTable (e.g., pagination, sorting) for persistence across page reloads.
stateNamespacestringcomponent IDNamespace for localStorage keys. Use unique values for multiple datatables on the same page.
columnsobjectundefinedOptional. Defines custom column rendering and cell creation logic.
Advanced Options
apiEndpointstringundefinedURL of the API endpoint for remote data fetching. When provided, enables remote mode.
mapResponsefunctionundefinedFunction to transform API response. Receives response data, must return {data: [], totalCount: number}.
mapRequestfunctionundefinedFunction to customize query parameters. Receives URLSearchParams object, must return modified URLSearchParams.
sort.callbackfunctiondefault sortCustom sorting function for local data. Receives (data, sortField, sortOrder), must return sorted array.
search.callbackfunctiondefault searchCustom search function for local data. Receives (data, searchQuery), must return filtered array.
search.delaynumber500Debounce delay in milliseconds before applying search filter.
checkbox.checkedClassstring"checked"CSS class to apply to checked rows.
checkbox.preserveSelectionbooleantrueWhether to preserve selection across page changes and data reloads.

Selectors

This table details the custom classes and data attributes used by the DataTable component.

NameDescription
Data Attributes
data-kt-datatableUsed to auto-initialize KTDataTable instances on page load. Alternatively, you can remove it and perform initialization using JavaScript.
data-kt-datatable-tableIdentifies the main table element for the DataTable.
data-kt-datatable-columnUsed on <th> elements to identify columns.
data-kt-datatable-column-sortUsed on <th> elements to enable sorting for that column.
data-kt-datatable-searchUsed on <input> elements to connect a search field to a DataTable. Value must be a CSS selector (e.g., "#my_datatable") matching the DataTable container's id attribute.
data-kt-datatable-checkIdentifies the group checkbox control used to select multiple rows.
data-kt-datatable-row-checkIdentifies the individual checkbox control for each row.
data-kt-datatable-infoIdentifies the element that displays the current page number and total pages.
data-kt-datatable-sizeMarks the select control that allows users to change the number of records displayed per page.
data-kt-datatable-paginationIdentifies the pagination element that enables users to navigate through different pages.
Classes
kt-tableBase class for the DataTable element. It wraps the entire table content and provides basic styling and behavior.
kt-table-gridAdds border styling to the DataTable for visual separation and emphasis.
kt-table-sortEnables sorting functionality for the DataTable columns.
kt-table-sort-labelApplied to the label element within the sortable column to indicate sorting.
kt-table-sort-iconApplied to the icon element within the sortable column to visually represent sorting direction.
ascIndicates that a column in the DataTable is sorted in ascending order.
descIndicates that a column in the DataTable is sorted in descending order.

Tailwind Modifiers

Custom modifiers to control the DataTable's style and behavior with Tailwind classes.

NameDescription
kt-datatable-loadingApplies specific styles when the DataTable is loading, triggered by actions such as pagination, page size change, or sorting.
kt-datatable-initializedApplies specific styles when the DataTable has fully initialized and is ready for user interaction.
kt-datatable-sort-ascApplies specific styles when a column in the DataTable is sorted in ascending order.
kt-datatable-sort-descApplies specific styles when a column in the DataTable is sorted in descending order.

Methods

Use KTDataTable component's API methods to programmatically control its behavior.

MethodDescription
new KTDataTable(element, options)Creates an instance of the KTDataTable class for the given DOM element and configuration options. This initializes the DataTable with the specified settings and binds it to the provided HTML element.
sort(field: string | number)Sorts the DataTable based on the specified field, which can be a column name string or column index number. This method reorders the rows according to the sort criteria applied to the field.
search(query: string | object)Searches the DataTable for rows that match the specified text string or object. This method filters the rows to display only those that contain the search query.
goPage(page: number)Navigates to the specified page number in the DataTable. This method updates the displayed rows to correspond with the chosen page.
reload()Reloads the DataTable data. This method refreshes the DataTable, fetching the latest data and updating the display accordingly.
setPageSize(pageSize: number)Sets the number of records to display per page in the DataTable. This method adjusts the pagination settings to accommodate the specified page size.
redraw(page: number)Redraws the DataTable at the specified page number. Useful for manual pagination updates.
setFilter(filter: object)Sets a column filter. Accepts an object with column, type, and value properties.
showSpinner()Displays a loading spinner overlay on the DataTable. This method is useful for indicating that data is being loaded or processed.
hideSpinner()Hides the loading spinner overlay from the DataTable. This method is used to indicate that data loading or processing is complete.
dispose()Removes the KTDataTable instance from an element, including any associated data stored on the DOM element.
isChecked()Returns true if the group checkbox is checked, otherwise false.
toggle()Toggles the group checkbox state between checked and unchecked.
check()Checks all visible row checkboxes.
uncheck()Unchecks all visible row checkboxes.
getChecked()Returns an array of the checked row IDs.
update()Reapplies checked state to visible checkboxes (after redraw/pagination).
getState()Returns the current state object of the DataTable.
const datatableEl = document.querySelector('#my_datatable');
const options = {
  pageSize: 5,
  stateSave: true,
};
const datatable = new KTDataTable(datatableEl, options);
 
datatable.reload();
datatable.showSpinner();

Utilities

Manage and interact with KTDataTable instances using these static methods of the KTDataTable JavaScript class.

MethodDescription
init()Automatically initializes KTDataTable objects for all elements with the data-kt-datatable="true" attribute on page load.
createInstances()Creates KTDataTable instances for all elements that have been dynamically added to the DOM but haven't been activated yet.
getInstance(element)Returns the KTDataTable object associated with the given DOM element element.
// Initialize all datatables
KTDataTable.init();
 
// Initialize pending datatables
KTDataTable.createInstances();
 
// Get datatable object
const datatableEl = document.querySelector('#my_datatable');
const datatable = KTDataTable.getInstance(datatableEl);

Events

KTDataTable custom events allow you to register callback functions (event listeners) that will be invoked automatically whenever specific custom events are triggered within the component.

EventDescription
initTriggered immediately after the DataTable is initialized.
drawTriggered immediately before the DataTable is drawn and displayed.
drewTriggered immediately after the DataTable is drawn and displayed.
redrawTriggered immediately after the DataTable is redrawn, typically after updates or changes.
fetchTriggered immediately before data is fetched for the DataTable.
fetchedTriggered immediately after data has been fetched for the DataTable.
sortTriggered immediately after the DataTable is sorted.
checkedTriggered immediately after rows checkbox is checked.
uncheckedTriggered immediately after rows checkbox is unchecked.
changedTriggered after any checkbox state change, in addition to checked/unchecked events.
changeTriggered before checkbox state changes. Can be cancelled by setting event.detail.cancel = true.
reloadTriggered immediately after the DataTable is reloaded.
paginationTriggered immediately before the DataTable pagination is updated.
stateSaveTriggered immediately before the DataTable state is saved.
errorTriggered if there is an error during data fetching or processing.
parseErrorTriggered when JSON parsing of API response fails (remote mode only).
const datatableEl = document.querySelector('#my_datatable');
const options = {
  pageSize: 5,
  stateSave: true,
};
const datatable = new KTDataTable(datatableEl, options);
 
datatable.on('init', () => {
  console.log('init event');
});
 
datatable.on('draw', () => {
  console.log('draw event');
});

Event Usage Patterns

Lifecycle Events - Show Loading Indicators:

const datatable = new KTDataTable(element, options);
const loadingOverlay = document.querySelector('#loading-overlay');
 
// Show loading on data fetch
datatable.on('fetch', () => {
  loadingOverlay.classList.remove('hidden');
});
 
// Hide loading when data loaded
datatable.on('fetched', () => {
  loadingOverlay.classList.add('hidden');
});
 
// Handle errors
datatable.on('error', (event) => {
  loadingOverlay.classList.add('hidden');
  console.error('Error loading data:', event.detail.error);
});
 
// Handle JSON parse errors (remote mode)
datatable.on('parseError', (event) => {
  loadingOverlay.classList.add('hidden');
  console.error('Failed to parse response:', {
    status: event.detail.status,
    statusText: event.detail.statusText,
    error: event.detail.error
  });
  // Show user-friendly error message
  alert('Failed to load data. Please try again later.');
});

Interaction Events - Track User Actions:

datatable.on('sort', (event) => {
  const { field, order } = event.detail;
  console.log(`Table sorted by ${field} in ${order} order`);
 
  // Send analytics event
  analytics.track('table_sorted', { field, order });
});
 
datatable.on('pagination', (event) => {
  const { page } = event.detail;
  console.log(`Navigated to page ${page}`);
 
  // Update URL without page reload
  const url = new URL(window.location);
  url.searchParams.set('page', page);
  window.history.pushState({}, '', url);
});
 
datatable.on('checked', (event) => {
  const checkedIds = datatable.getChecked();
  console.log(`Selected ${checkedIds.length} rows:`, checkedIds);
 
  // Enable bulk actions
  document.querySelector('#bulk-actions').disabled = false;
});
 
datatable.on('unchecked', () => {
  const checkedIds = datatable.getChecked();
  if (checkedIds.length === 0) {
    // Disable bulk actions when nothing selected
    document.querySelector('#bulk-actions').disabled = true;
  }
});
 
// Track all checkbox changes (fires for any check/uncheck)
datatable.on('changed', () => {
  const checkedIds = datatable.getChecked();
  console.log(`Selection changed. Currently selected: ${checkedIds.length} rows`);
 
  // Update UI based on selection count
  const selectionCount = document.querySelector('#selection-count');
  selectionCount.textContent = `${checkedIds.length} selected`;
});
 
// Prevent checkbox changes conditionally (advanced)
datatable.on('change', (event) => {
  const checkedIds = datatable.getChecked();
 
  // Prevent more than 10 selections
  if (checkedIds.length >= 10) {
    event.detail.cancel = true;
    alert('Maximum 10 items can be selected');
  }
});

Data Manipulation After Render:

datatable.on('drew', () => {
  // Attach tooltips to newly rendered elements
  const tooltipElements = document.querySelectorAll('[data-tooltip]');
  tooltipElements.forEach(el => {
    new Tooltip(el);
  });
 
  // Initialize popovers
  const popoverElements = document.querySelectorAll('[data-popover]');
  popoverElements.forEach(el => {
    new Popover(el);
  });
 
  // Highlight search terms
  const searchQuery = datatable.getState().search;
  if (searchQuery) {
    highlightSearchTerms(searchQuery);
  }
});

Accessing DataTable Instance in Events:

datatable.on('init', function() {
  // 'this' refers to the datatable instance
  const state = this.getState();
  console.log('Initial state:', state);
 
  // Call instance methods
  if (state.page > 1) {
    this.goPage(1); // Reset to first page
  }
});
 
datatable.on('fetched', function() {
  const state = this.getState();
 
  // Update external UI elements
  document.querySelector('#total-records').textContent = state.totalItems;
 
  // Apply custom processing
  if (state.totalItems === 0) {
    document.querySelector('#empty-state').classList.remove('hidden');
  }
});

State Synchronization:

// Sync with external state management
datatable.on('stateSave', function() {
  const state = this.getState();
 
  // Save to Vuex/Redux/custom store
  store.commit('SET_DATATABLE_STATE', {
    page: state.page,
    pageSize: state.pageSize,
    sortField: state.sortField,
    sortOrder: state.sortOrder,
    selectedRows: state.selectedRows
  });
});
 
// Restore state on init
datatable.on('init', function() {
  const savedState = store.state.datatableState;
  if (savedState) {
    this.goPage(savedState.page);
    this.setPageSize(savedState.pageSize);
    if (savedState.sortField) {
      this.sort(savedState.sortField);
    }
  }
});

Event Parameter Details:

EventEvent Detail Properties
initnone
drawnone
drewnone
redrawnone
fetchnone
fetched{ response } (remote mode only, first fire)
sort{ field: string|number, order: 'asc'|'desc'|'' }
checkednone (use getChecked() method to retrieve IDs)
uncheckednone (use getChecked() method to retrieve IDs)
changednone (use getChecked() method to retrieve IDs)
change{ cancel: boolean } (set cancel: true to prevent change)
reloadnone
pagination{ page: number }
stateSavenone (use getState() method to retrieve full state)
error{ error }
parseError{ response, error: string, status: number, statusText: string }
PreviouseCollapseNextDatepicker

On This Page

  • Examples
    • Basic Usage
    • Remote Data Source
    • Group Check
  • How It Works
    • Component Architecture
    • Data Flow
  • Data Modes
    • Local Data Mode
    • Remote Data Mode
    • Credentials Configuration
    • Mode Detection
  • Local Data Guide
    • Using HTML Tables
    • Client-Side Behavior
    • Custom Local Sorting
    • Custom Local Search
    • Search Input Configuration
    • Performance Considerations
  • Column Configuration
    • Basic Column Customization
    • Render Function Signatures
    • CreatedCell Callback
    • Nested Object Fields
    • Custom CSS Classes
  • Advanced Configuration
    • API Response Transformation
    • API Request Customization
    • Loading State Customization
    • Custom Selectors
    • Complete Configuration Example
  • Components API
    • Options
    • Selectors
    • Tailwind Modifiers
    • Methods
    • Utilities
    • Events
    • Event Usage Patterns