Search documentation

Search for a page or heading...

tablecn
0

The ideas behind tablecn, explained with one example.

This page follows one view of an orders table: search for "nguyen", only paid orders, the biggest amounts first, page 2. Each section introduces one idea you'll see in the rest of the docs.

The URL holds the view

Everything that decides which rows you see is written to the URL:

URL
/orders?q=nguyen&status__eq=paid&sort=-amount&page=2
ParamWritten byMeaning
q=nguyenthe search boxrows containing "nguyen"
status__eq=paidthe filterStatus is Paid
sort=-amounta header clickbiggest amount first (- means descending)
page=2the paginationthe second page

So users can reload, share a link, or press Back, and get the same view. An adapter connects this to your router: Next.js, react-router or the plain browser history. When a URL is read, everything in it is checked: a broken or outdated link gives a smaller view, never an error.

Learn more in URL state.

Columns: what the table shows

Columns are TanStack Table column definitions. Each one has an id, which is also the name used in sort=:

Columns
const column = createDataTableColumnHelper<Order>()

export const orderColumns = [
  column.accessor("customer", { header: "Customer" }),
  column.accessor("amount", { header: "Amount" }),
]

useDataTable turns your columns and rows into a table, with the search, sort and page read from the URL. Learn more in Columns.

Fields: what users can filter by

Fields are the filter's side. Each has a name, a label and a type:

Fields
export const orderFields: FieldDefinition[] = [
  { name: "status", label: "Status", type: "select", options: [/* … */] },
  { name: "amount", label: "Amount", type: "number" },
]

The type decides which operators users get: a number field offers "is greater than", a text field "contains". Learn more in Fields.

Rules: one condition each

Each condition in the filter is a rule: a field, an operator and a value.

What the user seesfieldoperatorvalue
Status is Paidstatuseq"paid"
Amount is between 10 and 50amountbetween[10, 50]

Rules are combined with AND (every rule must match) or OR (any rule may match). The operator decides the value's shape (called its arity): nothing for is empty, one value for is, a pair for is between, a list for is any of. See every operator in Operators.

While users edit rules, nothing changes. Only Apply writes the complete rules to the URL, so your data doesn't reload on every keystroke.

Client or server data

Someone has to do the searching, filtering, sorting and paging:

Client mode (default)Server mode
You passevery rowone page of rows, and the total
The work is done bythe browseryour backend
Good forup to a few thousand rowsanything bigger

In server mode, tablecn reads the URL and builds the request for you. The same view becomes:

BackendRequest
JSON:API stylefilter[status][eq]=paid&sort=-amount&page[number]=2&page[size]=20&filter[search]=nguyen
django-filter / DRFstatus=paid&ordering=-amount&page=2&page_size=20&search=nguyen
your ownwhatever your API expects

Learn more in Server data.

The layout is personal

Hidden columns, their order, pins, widths and colors are the layout. It isn't in the URL: a shared link shows the same rows, but each user keeps their own columns. The layout is saved in the browser under a storageKey you choose. Learn more in Layout.

Where each piece lives

The UI comes from the two registry blocks, the logic from the @querycn packages. The Packages table lists what each one does.