---
title: Table
description: Display multiple records in declared columns.
---

A table block displays multiple records through a declared set of fields. Use it when
people must scan and compare records.

The fields control the column order, headings, and display variants. The data
supplies the raw rows. The SDK remaps each cell to the protocol format before it
sends the node.

## API

```ts
table(data: Row[]): TableBuilder<Row>
```

| Method       | Input                      | Result                                              |
| ------------ | -------------------------- | --------------------------------------------------- |
| `setFields`  | `Nodeable<Field>[]`        | Sets the columns and their order.                   |
| `withFooter` | `{ label, values }[]`      | Sets summary rows below the data.                   |
| `onDefect`   | `(defect: Defect) => void` | Handles values that the SDK cannot put on the wire. |

Calling `setFields` or `withFooter` again replaces the previous
value.

## Basic table

Pass the raw rows to `table(data)`, then set the fields. Each declared field becomes one column.

<BacklitExample path="table/basic" view="list" />

## Table inside a panel

Put a table inside a panel when the records need a title, description, filters,
or a bounded surface. The table remains the panel content.

<BacklitExample path="table/panel" view="list" />

## Empty table

Pass an empty array when the query returns no records. The protocol contains an
empty data array. The renderer supplies the empty state.

<BacklitExample path="table/empty" view="list" />

## Selected fields

Use `resource.pick` to select columns and set their order. Extra keys in a raw
row do not go into the protocol output.

<BacklitExample path="table/selected_fields" view="list" />

## Default remapping

The default remapper converts every cell to the format for its field kind. It
can convert numeric strings, boolean inputs, and date inputs.

<BacklitExample path="table/remapping" view="list" />

## Footer

Use `withFooter` for totals and other summaries. Put each value under the field
that it summarizes. The renderer puts the label in the columns before the first
footer value.

The first table field cannot contain a footer value because the footer label
needs at least one column.

<BacklitExample path="table/footer" view="detail" />

### Multiple footer rows

Pass multiple footer rows for a subtotal, tax, total, or another sequence of
summaries. A footer row can contain values for more than one field.

<BacklitExample path="table/multiple_footer_rows" view="detail" />

## Global remapper

Use `remappers.registerRemappers` when an adapter uses a different value format.
The change applies to the role in all blocks. A table does not accept local
remapper overrides.

<BacklitExample path="table/custom_remapper" view="list" />

## Defect reporter

A defect occurs when a cell is missing or its value cannot be remapped. The SDK
leaves that cell out of the row and includes its row index in the defect. If you
do not set a reporter, the SDK writes a warning to the console.

<BacklitExample path="table/defect_reporter" view="list" />

## All options

You can use footer rows and a defect reporter on the same table.

<BacklitExample path="table/all_options" view="list" />

## Field roles

`setRoles({ fieldName: role })` selects roles for individual fields and replaces
the previous selections. The default role is `display` in tables and datalists,
and `input` in form field blocks. See [Field roles](/advanced/field-roles).

## Row controls and search state

Use `onRowClick(linkTo(view, row => [row.id]))` to make each row a link.
Use `setRowActions` for standalone visit or action controls. See
[Targets](/reference/targets). Use `setPaginator` and `setSorter` to place state
bindings from one view or zone scope. The resolver must apply the parsed state
to the data query. See [Search state](/reference/state).
