Skip to main content
A table is a grid of columns with an optional header row and a body that repeats one row per element in an array from your data. Repeating table rows is the only loop in the template language — there are no other loops or conditionals.

Columns

Columns are sized exactly like row cellsrelative by weight, or constant by width:
The number of columns sets the grid; every header and body row must supply exactly that many cells.

Repeating rows with forEach

The body’s forEach is a dotted path into data that must resolve to an array. Tipar renders the row template once per element, binding the current element to item:
Given this data, the body renders three rows:
item is only defined inside a table body. Referencing {{item.x}} anywhere else, or pointing forEach at something that isn’t an array, fails with 422.
Need a row that isn’t part of the loop — a totals line, a “no items” note? Put it outside the table, as a sibling node in the surrounding column. The table is strictly the repeating grid; static lines live next to it.

Cells

Every cell — header or body — has the same shape:

Cell borders

In v1 a cell border is a bottom rule only — enough for the horizontal lines that make up most tables. Top, left, and right borders aren’t supported yet. A common pattern: a darker, heavier rule under the header, and a light hairline under each body row.
Cell counts must match the column count. If columns has three entries, every header.row and body.row must have exactly three cells. A mismatch is a 422 structural error — and the response names the offending row so you can fix it.

Multi-page tables

You don’t manage pagination. When a table’s rows overflow the page, Tipar continues it on the next page automatically, re-drawing the header row at the top. Combine that with a page-number footer for long reports — see the report example.

Next: Images

Embed logos and graphics as base64.