Column
Column defines the structure and behavior of individual table columns within a Table component. Each Column controls data binding, header display, sorting capabilities, sizing, and can contain any XMLUI components for rich cell content.
Key features:
- Data binding: Use
bindToto automatically display object properties - Typed cells: Use
typefor common table-cell formatting such as email links, dates, numbers, currency, enum labels, JSON, and interactive checkbox, switch, or color cells - Component embedding: Place any component inside
Column:Button,Text,Icon, etc. - Interactive behavior: Enable/disable sorting and column resizing
- Layout control: Set width using pixels, star sizing (
*,2*), or proportional values - Column pinning: Pin columns to left or right edges for sticky behavior
Column can bind a field, display that field with a type hint, render an interactive typed control, or render completely custom child markup.
The type property does not validate or convert the underlying data.
When you place child components inside a Column, that custom content overrides type rendering.
You can pass layout properties to a Column:
<App>
<Table data='{[...]}'>
<Column bindTo="name" />
<Column
bindTo="quantity"
horizontalAlignment="right"
backgroundColor="lightyellow"
/>
<Column bindTo="unit" />
</Table>
</App>Context variables available during execution:
$cell: The specific cell value for this column$colIndex: Zero-based column index$item: The complete data row object being rendered$itemIndex: Zero-based row index$row: The complete data row object being rendered (the same as$item).$rowIndex: Zero-based row index (the same as$itemIndex).
Behaviors
No behaviors are applicable to this component.
Properties
bindTo
Indicates the name of the current row item's property, the value of which to lay out in the column. If this property is not defined, the column is not sortable.
<App>
<Table data='{[...]}'>
<Column bindTo="name" />
</Table>
</App>canResize
This property indicates whether the user can resize the column. If set to true, the column can be resized by dragging the column border. If set to false, the column cannot be resized. When omitted, the column uses the parent Table component's canResizeColumns value. Double-clicking the column border resets to the original size.
canSort
default: true
This property sets whether the user can sort by a column by clicking on its header (true) or not (false). If the bindTo property is not defined, the column is not sortable.
Columns with bindTo are sortable by default. Click on the Name or Quantity column headers to order the data. The Unit column has sorting explicitly disabled with canSort="false".
<App>
<Table data='{[...]}'>
<Column bindTo="name" />
<Column bindTo="quantity" />
<Column canSort="false" bindTo="unit" />
</Table>
</App>To change the default for all columns in your app, set columnCanSortDefault in config.json:
{
"xmluiConfig": {
"columnCanSortDefault": false
}
}enabled
default: true
This property controls whether interactive typed cells in the column respond to user events. It is applied to the underlying control for checkbox, switch, and color column types.
Set enabled="false" to disable interactive typed cells.
This property is true by default and is applied to the underlying control for checkbox, switch, and color column types.
<Table data="{[
{ selected: true, enabled: false, accent: '#336699' }
]}">
<Column bindTo="selected" type="checkbox" enabled="false" />
<Column bindTo="enabled" type="switch" enabled="false" />
<Column bindTo="accent" type="color" enabled="false" />
</Table><Table data="{[
{ selected: true, enabled: false, accent: '#336699' }
]}">
<Column bindTo="selected" type="checkbox" enabled="false" />
<Column bindTo="enabled" type="switch" enabled="false" />
<Column bindTo="accent" type="color" enabled="false" />
</Table>header
This property defines a label for a particular column. If not set, the bindTo property value is used for the label.
<App>
<Table data='{[...]}'>
<Column header="Food Name" bindTo="name" />
<Column header="Food Quantity" bindTo="quantity" />
<Column bindTo="unit" />
</Table>
</App>headerHorizontalAlignment
This property sets the horizontal alignment of the column header content, including the sort indicator.
Available values: start, center, end
headerHorizontalAlignment sets the horizontal alignment of the header content.
The header text and the sort indicator are aligned together.
Use start, center, or end.
<Table
data="{[
{ name: 'Apples', quantity: 5 },
{ name: 'Bananas', quantity: 6 }
]}"
alwaysShowSortingIndicator
>
<Column bindTo="name" header="Name" headerHorizontalAlignment="start" />
<Column bindTo="quantity" header="Quantity" headerHorizontalAlignment="end" />
</Table><Table
data="{[
{ name: 'Apples', quantity: 5 },
{ name: 'Bananas', quantity: 6 }
]}"
alwaysShowSortingIndicator
>
<Column bindTo="name" header="Name" headerHorizontalAlignment="start" />
<Column bindTo="quantity" header="Quantity" headerHorizontalAlignment="end" />
</Table>maxWidth
Indicates the maximum width a particular column can have. Same rules apply as with width.
minWidth
Indicates the minimum width a particular column can have. Same rules apply as with width.
pinTo
This property allows the column to be pinned to the left (left-to-right writing style) or right (left-to-right writing style) edge of the table. If the writing style is right-to-left, the locations are switched. If this property is not set, the column is not pinned to any edge.
Available values: left, right
By default, the background color of table rows is transparent. When using the
pinToproperty, you should set the background to an explicit (non-transparent) color; otherwise, the scrolled cells will be visible under the pinned columns.
<App>
<Theme backgroundColor-row-Table="$color-surface-0">
<Table data='{[...]}' height="100%">
<Column bindTo="id" width="50px" pinTo="left" />
<Column bindTo="name" width="500px" />
<Column bindTo="quantity" width="300px" />
<Column bindTo="unit" width="300px"/>
<Column bindTo="category" width="100px" pinTo="right"/>
</Table>
</Theme>
</App>Scroll the table contents horizontally to see how the pinned columns are displayed.
readOnly
default: false
This property marks interactive typed cells in the column as read-only. It is applied to the underlying control for checkbox, switch, and color column types.
Set readOnly to prevent users from changing interactive typed cells.
This property is applied to the underlying control for checkbox, switch, and color column types.
<Table data="{[
{ selected: true, enabled: false, accent: '#336699' }
]}">
<Column bindTo="selected" type="checkbox" readOnly />
<Column bindTo="enabled" type="switch" readOnly />
<Column bindTo="accent" type="color" readOnly />
</Table><Table data="{[
{ selected: true, enabled: false, accent: '#336699' }
]}">
<Column bindTo="selected" type="checkbox" readOnly />
<Column bindTo="enabled" type="switch" readOnly />
<Column bindTo="accent" type="color" readOnly />
</Table>tooltip
This property sets the tooltip text shown when hovering over cells in this column.
Set tooltip to show text when users hover over cells in the column.
The tooltip is evaluated for each cell, so it can use Column context variables such as $item, $row, $cell, $itemIndex, $rowIndex, and $colIndex.
Use tooltipOptions to configure the tooltip position, delay, arrow, and collision behavior.
Like tooltip behavior options on visual components, tooltipOptions accepts either an object or a semicolon-separated string.
<Table data="{[
{ id: 1, name: 'Ada', enabled: true }
]}">
<Column
bindTo="name"
tooltip="{$item.id + ' - ' + $cell}"
tooltipOptions="{{side:'right', delayDuration:0}}"
/>
<Column
bindTo="enabled"
type="switch"
tooltip="Toggle whether the contact is enabled"
tooltipOptions="side:bottom; delayDuration:0"
/>
</Table><Table data="{[
{ id: 1, name: 'Ada', enabled: true }
]}">
<Column
bindTo="name"
tooltip="{$item.id + ' - ' + $cell}"
tooltipOptions="{{side:'right', delayDuration:0}}"
/>
<Column
bindTo="enabled"
type="switch"
tooltip="Toggle whether the contact is enabled"
tooltipOptions="side:bottom; delayDuration:0"
/>
</Table>tooltipOptions
This property sets options for configuring column cell tooltips, such as delay and position.
Set tooltipOptions to configure the tooltip shown for cells in this column.
The accepted options match the Tooltip component: delayDuration, skipDelayDuration, defaultOpen, showArrow, side, align, sideOffset, alignOffset, and avoidCollisions.
You can provide the options as an object or as a semicolon-separated string.
<Table data="{[
{ name: 'Ada', enabled: true }
]}">
<Column
bindTo="name"
tooltip="Shown on the right"
tooltipOptions="{{side:'right', align:'center', delayDuration:0}}"
/>
<Column
bindTo="enabled"
type="switch"
tooltip="Shown below"
tooltipOptions="side:bottom; align:start; delayDuration:0"
/>
</Table><Table data="{[
{ name: 'Ada', enabled: true }
]}">
<Column
bindTo="name"
tooltip="Shown on the right"
tooltipOptions="{{side:'right', align:'center', delayDuration:0}}"
/>
<Column
bindTo="enabled"
type="switch"
tooltip="Shown below"
tooltipOptions="side:bottom; align:start; delayDuration:0"
/>
</Table>type
This property provides a display hint for the column's cell values. Use compact values such as text, email, number(8,3), currency(USD), date(short), datetime, boolean, checkbox, switch, color, enum, image, or json to select common table cell behavior. The type does not validate, convert, or mutate the underlying data. The checkbox, switch, and color types render interactive controls. Custom child markup inside the Column overrides type rendering.
type tells the table how to display the column's bound values.
Use it for common display semantics without writing custom cell markup.
The type does not validate, convert, or mutate the underlying data.
The checkbox, switch, and color types render interactive controls and can fire didChange.
If a value cannot be formatted for the selected type, the table falls back to plain text for that cell.
Use Value for the same read-only typed display behavior outside tables.
Type Syntax
Use a bare type name for the default behavior:
<Column bindTo="email" type="email" />Some types accept positional arguments:
<Column bindTo="amount" type="number(8,3)" />
<Column bindTo="total" type="currency(EUR)" />
<Column bindTo="createdAt" type="datetime(short)" />Some types accept named arguments:
<Column bindTo="site" type="url(label:domain)" />
<Column bindTo="note" type="long-text(lines:2)" />typeOptions can provide the same kind of options as an object.
When both compact type arguments and typeOptions provide the same option, typeOptions wins.
Locale-aware typed cells use the root App locale or the nearest Locale
wrapper by default. Set typeOptions.locale to format an individual column
with a specific BCP-47 locale; that explicit column locale wins over Locale.
<Column bindTo="note" type="long-text(lines:2)" typeOptions="{{maxLines:4}}" />
<Column bindTo="amount" type="currency(EUR)" typeOptions="{{locale:'hu-HU'}}" />Text and Identifier Types
| Type | Visual traits | Useful options |
|---|---|---|
text | Plain text cell. | None. |
short-text | Plain text with compact text styling, useful for short labels and codes. | None. |
long-text | Wrapped text. Can be clamped to a fixed number of visual lines; clamped cells show the full text as a title tooltip by default. | long-text(lines:2), typeOptions="{{maxLines:2}}", typeOptions="{{tooltip:false}}". |
markdown | Inline Markdown for **bold** and *italic*; also supports line clamping. | markdown(lines:2) or typeOptions="{{maxLines:2}}". |
code | Monospace code-style text. | None. |
id | Compact identifier text. Long values are shortened to the first eight characters followed by ... by default. | id(short) or id(full). |
uuid | Compact text styling for UUID-shaped identifiers; the full value is displayed. | None. |
name | Plain name text with normal table-cell styling. | None. |
address | Wrapped address text. Can be clamped like long-text. | address(lines:2) or typeOptions="{{maxLines:2}}". |
Link Types
| Type | Visual traits | Useful options |
|---|---|---|
email | Renders an anchor with a mailto: URL and displays the email address. | None. |
phone | Renders an anchor with a tel: URL and displays the phone number. | None. |
url | Renders an anchor using the cell value as the href. | url(label:domain) displays the hostname. url(label:'Open') displays a fixed label. |
link | Same link renderer as url; use it when the value is a generic hyperlink. | link(label:domain) or link(label:'Open'). |
Numeric Types
Numeric types are aligned to the end of the cell by default.
The renderer separates integer, decimal, fraction, and suffix parts so decimals line up consistently across rows.
For number, integer, decimal, percent, currency, accounting, scientific, bytes, and rating, invalid numeric values fall back to plain text.
| Type | Visual traits | Useful options |
|---|---|---|
number | Locale-formatted number. | number(8,3) accepts precision and scale; the current formatter uses the scale as the maximum number of fractional digits. Use typeOptions="{{locale:'hu-HU'}}" to override the app or scoped locale for this column. |
integer | Locale-formatted number rounded to zero fractional digits. | None. |
decimal | Locale-formatted decimal with a fixed number of fractional digits. | decimal(2). |
percent | Locale-formatted percentage. For example, 0.12 displays as 12%. | None. |
currency | Locale-formatted currency. | currency(USD), currency(EUR), or typeOptions="{{currency:'USD'}}". Defaults to USD. |
accounting | Locale-formatted currency with accounting sign display where the locale supports it. | accounting(USD) or typeOptions="{{currency:'USD'}}". Defaults to USD. |
scientific | Locale-formatted scientific notation. | None. |
bytes | Scales a byte count to B, KB, MB, GB, or TB with up to one fractional digit. | None. |
duration | Interprets the value as seconds and displays a compact duration such as 1h 1m 1s. Negative values display as 0s. | None. |
rating | Displays the value against a maximum, such as 4 / 5. | rating(5) or typeOptions="{{max:10}}". Defaults to 5. |
Date and Time Types
Date and time types accept Date values and date-compatible strings or numbers.
Invalid date values fall back to plain text.
| Type | Visual traits | Useful options |
|---|---|---|
date | Locale-formatted date. Defaults to medium date style. | date(short), date(medium), date(long), or date(full). |
time | Locale-formatted time. Defaults to short time style. | time(short), time(medium), time(long), or time(full). |
datetime | Locale-formatted date and time. Defaults to short date and short time style. | datetime(short), datetime(medium), datetime(long), or datetime(full). |
relative-time | Displays a relative value such as 1 hour ago or tomorrow, based on the current time. | None. |
timestamp | Displays the JavaScript timestamp in milliseconds. | None. |
iso-date | Displays the ISO calendar date portion, such as 2026-08-06. | None. |
Choice and Boolean Types
enum and status render as plain text by default.
Use typeOptions to map raw values to readable labels; visual badges require custom Column child content.
| Type | Visual traits | Useful options |
|---|---|---|
boolean | Displays true or false. | None. |
checkbox | Displays a checkbox control for truthy or falsy values. | None. |
switch | Displays a switch control for truthy or falsy values. | None. |
yes-no | Displays Yes or No. | None. |
enum | Displays the raw value or a mapped label as plain text. | typeOptions="{{sent:{label:'Sent'}, draft:'Draft'}}" or typeOptions="{{values:{sent:'Sent'}}}". |
status | Displays the raw value or a mapped label as plain text. | Same mapping options as enum. |
Visual and Structured Types
| Type | Visual traits | Useful options |
|---|---|---|
color | Displays a color picker control. | None. |
tag | Displays a single value with tag-like styling. | None. |
tags | Displays arrays as comma-separated values with tag-like styling. Non-array values display as text. | None. |
image | Displays the cell value as an image URL. | typeOptions="{{alt:'Thumbnail'}}" for accessible alt text. |
avatar | Displays the cell value as a rounded avatar image URL. | typeOptions="{{label:'Ada avatar'}}" or typeOptions="{{alt:'Ada avatar'}}". |
icon | Displays an XMLUI icon and its icon name. | None. |
json | Displays JSON.stringify(value) in code styling. null displays as null. | None. |
object | Displays objects with JSON.stringify(value) in code styling. | None. |
array | Displays arrays with JSON.stringify(value) in code styling. | None. |
list | Displays arrays as comma-separated values. Non-array values display as text. | None. |
number(8,3) displays numeric values with up to three fractional digits and uses a decimal-aware cell structure:
long-text can clamp wrapped content to a maximum number of visual lines.
Use compact syntax or typeOptions; typeOptions wins when both are provided:
If a Column has child content, the child content is rendered instead of the typed default:
typeOptions
This property provides additional display options for the column type. Use it for object-shaped configuration, such as enum/status label maps, link labels, or image/avatar alt text, and long-text options such as maxLines. Values in typeOptions override compact options specified in the type string.
typeOptions provides object-shaped display options for the selected type.
It is most useful when compact type syntax is not expressive enough.
For enum and status, values render as plain text by default.
Use typeOptions to map raw values to readable labels:
The same pattern works for status; it still renders plain text unless you provide custom child content:
For image and avatar, use typeOptions for accessible labels:
width
This property defines the width of the column. You can use a numeric value, a pixel value (such as 100px), or a star size value (such as *, 2*, etc.). You will get an error if you use any other unit (or value).If not defined, the component will use a width according to the column values and the available space.
The following example sets the second column to an absolute size (size pixels), while the first and third columns have star sizes:
<App>
<Table data='{[...]}'>
<Column bindTo="name" canResize="true" width="3*" />
<Column bindTo="quantity" width="100px" minWidth="50px" maxWidth="500px" />
<Column bindTo="unit" width="*" />
</Table>
</App>Check what happens when you resize table columns:
Events
didChange
This event is triggered when an interactive typed cell in the column changes its value.
Signature: didChange(newValue: any, row: any, rowIndex: number, columnId: string): void
newValue: The new cell value.row: The row data object associated with the changed cell.rowIndex: The zero-based visible row index.columnId: The column identifier.
didChange runs after an interactive typed cell has accepted a new value.
The event receives the new value, the row object, the zero-based visible row index, and the column id.
<Fragment var.rows="{[{ selected: false, accent: '#336699' }]}">
<Table data="{rows}">
<Column
bindTo="selected"
type="checkbox"
onDidChange="(newValue, row) => row.selected = newValue"
/>
<Column
bindTo="accent"
type="color"
onDidChange="(newValue, row) => row.accent = newValue"
/>
</Table>
</Fragment><Fragment var.rows="{[{ selected: false, accent: '#336699' }]}">
<Table data="{rows}">
<Column
bindTo="selected"
type="checkbox"
onDidChange="(newValue, row) => row.selected = newValue"
/>
<Column
bindTo="accent"
type="color"
onDidChange="(newValue, row) => row.accent = newValue"
/>
</Table>
</Fragment>willChange
This event is triggered before an interactive typed cell in the column changes its value. Return explicit false to cancel the change.
Signature: willChange(newValue: any, row: any, rowIndex: number, columnId: string): boolean | void
newValue: The new cell value.row: The row data object associated with the changed cell.rowIndex: The zero-based visible row index.columnId: The column identifier.
willChange runs before an interactive typed cell commits a new value.
Return explicit false to cancel the change. Returning undefined or omitting a return value allows the change to continue.
<Fragment var.rows="{[{ selected: false }]}">
<Table data="{rows}">
<Column
bindTo="selected"
type="checkbox"
onWillChange="(newValue) => newValue === true ? false : undefined"
onDidChange="(newValue, row) => row.selected = newValue"
/>
</Table>
</Fragment><Fragment var.rows="{[{ selected: false }]}">
<Table data="{rows}">
<Column
bindTo="selected"
type="checkbox"
onWillChange="(newValue) => newValue === true ? false : undefined"
onDidChange="(newValue, row) => row.selected = newValue"
/>
</Table>
</Fragment>Exposed Methods
This component does not expose any methods.
Styling
Styling is done via the Table component.