Data Table

A table component with sorting, filtering, and pagination compatible with VitNode API.

Preview

Usage

import { DataTable } from "@vitnode/core/components/table/data-table";
<DataTable
  id="users-table"
  columns={[
    { id: "name", label: "Name" },
    { id: "email", label: "Email" },
    { id: "role", label: "Role" },
    { id: "status", label: "Status" },
    { id: "id", label: "Actions" },
  ]}
  edges={data.edges}
  pageInfo={data.pageInfo}
  order={{
    defaultOrder: {
      column: "name",
      order: "asc",
    },
  }}
/>

Prop

Type

Cell Renderer

You can customize how each cell is rendered using the cell property. The renderer function receives the current row data and all table data as parameters.

<DataTable
  id="users-table"
  columns={[
    {
      id: "id",
      label: "Id",
      cell: ({ row, allData }) => (
        <span>
          {row.id} - all data {allData.length}
        </span>
      ),
    },
    { id: "createdAt", label: "Created at" },
  ]}
  edges={data.edges}
  pageInfo={data.pageInfo}
  order={{
    columns: ["createdAt", "id"],
    defaultOrder: {
      order: "desc",
    },
  }}
/>

Order Configuration

If you want to enable sorting on specific columns, you can specify them in the columns property.

order={{
  columns: ['createdAt', 'id', 'name'],
  defaultOrder: {
    column: 'createdAt',
    order: 'desc',
  }
}}

Set the search prop to true to render a search input above the table. You can optionally customize the placeholder with searchPlaceholder.

<DataTable
  id="users-table"
  search
  searchPlaceholder="Search users..."
  columns={[
    { id: "name", label: "Name" },
    { id: "email", label: "Email" },
  ]}
  edges={data.edges}
  pageInfo={data.pageInfo}
  order={{
    defaultOrder: {
      column: "name",
      order: "asc",
    },
  }}
/>

The input writes the term to the ?search= query parameter (debounced) and reloads the page, so it works out of the box with server-side data fetching. The columns that are actually searched are defined on the API route.

Configure the API route

Enabling search only renders the input. You must also tell the backend which columns to search across — see the Search guide.

Complete Example

Here's a complete example showing how to use the DataTable component in a page:

import {
  DataTable,
  SearchParamsDataTable,
} from "@vitnode/core/components/table/data-table";
import { userModule } from "@/api/modules/user/user.module";
import { fetcher } from "@vitnode/core/lib/fetcher";

export const UsersView = async ({
  searchParams,
}: {
  searchParams: Promise<SearchParamsDataTable>;
}) => {
  const query = await searchParams;
  const res = await fetcher(userModule, {
    path: "/users",
    method: "get",
    module: "user",
    args: {
      query,
    },
    withPagination: true,
  });
  const data = await res.json();

  return (
    <DataTable
      id="users-table"
      columns={[
        {
          id: "id",
          label: "ID",
        },
        {
          id: "username",
          label: "Username",
          cell: ({ row }) => (
            <span className="font-medium">{row.username}</span>
          ),
        },
        { id: "email", label: "Email" },
        { id: "createdAt", label: "Created at" },
      ]}
      edges={data.edges}
      order={{
        columns: ["id", "username", "email", "createdAt"],
        defaultOrder: {
          column: "createdAt",
          order: "desc",
        },
      }}
      pageInfo={data.pageInfo}
    />
  );
};

On this page