Search documentation

Search for a page or heading...

tablecn
0

Define what the table shows, and what users can do with each column.

Columns are TanStack Table column definitions, with a few extra options tablecn reads. Build them with createDataTableColumnHelper, which types those options for you:

components/orders/order-columns.tsx
"use client"

import { createDataTableColumnHelper } from "@querycn/table-react"

import { createSelectionColumn } from "@/components/data-table/data-table-selection-column"

interface Order {
  id: string
  customer: { name: string }
  status: "paid" | "pending"
  amount: number
  createdAt: string
}

const column = createDataTableColumnHelper<Order>()

export const orderColumns = [
  createSelectionColumn<Order>(),
  column.accessor("customer.name", {
    header: "Customer",
    size: 200,
    meta: { defaultPinned: "start" },
  }),
  column.accessor("status", { header: "Status" }),
  column.accessor("amount", {
    header: "Amount",
    sortDescFirst: true,
    cell: ({ getValue }) => getValue().toFixed(2),
  }),
  column.accessor("createdAt", { header: "Created", meta: { defaultHidden: true } }),
  column.display({
    id: "actions",
    header: () => <span className="sr-only">Actions</span>,
    meta: { label: "Actions" },
    enableHiding: false,
    cell: ({ row }) => <OrderActions order={row.original} />,
  }),
]

Define columns outside your components

Put the array at module scope, or wrap it in useMemo. A new array on every render rebuilds the table's columns.

Prefer writing the objects by hand? Type each one as DataTableColumnDef<Order>.

Column ids

Every column has an id. It's what appears in the URL (?sort=-customer_name), in the saved layout, and in data-column-id on every cell. It comes from, in order:

  1. an explicit id;
  2. the accessor key, with dots replaced by _: customer.name becomes customer_name;
  3. a string header.

Renaming a column's id breaks links and saved layouts that use the old one. See Layout for how to handle that.

Starting layout

meta sets how a column looks the first time a user sees the table, and after they press Reset layout:

Starting layout
column.accessor("customer.name", { header: "Customer", meta: { defaultPinned: "start" } })
column.accessor("createdAt", { header: "Created", meta: { defaultHidden: true } })

Prop

Type

Once users change the layout, their saved layout wins. See Layout.

What users can do

By default, users can sort, move, resize, hide, pin and color every column. Each has its own page; here are the switches in one place. Turn a feature off for the whole table in useDataTable, or for one column in its definition:

FeatureWhole table (useDataTable)One columnSee
SortenableSorting: falseenableSorting: falseSorting
Move (drag and drop)enableColumnOrdering: falsemeta.enableOrdering: falseMoving columns
Resize and fitenableColumnResizing: falseenableResizing: falseResizing
Hide—enableHiding: falseHiding columns
Pin—enablePinning: falsePinning
Color——Column colors
A table users can sort but not rearrange or resize
const table = useDataTable({
  data,
  columns,
  getRowId: (order) => order.id,
  enableColumnOrdering: false, 
  enableColumnResizing: false, 
})

A table-wide false wins over a column's true. Any other TanStack column option works too.

Sorting and selection

Sorting has its own page, Sorting, and so does the checkbox column, Row selection.

Grouped headers

Group columns under a shared header with column.group({ header, columns }). Sorting, resizing, pinning and hiding work on the inner columns. Dragging columns is turned off while there's more than one header row, since moving a column out of its group would break the group.