Columns
Columns are the building blocks of every table. Each column defines what data to extract from your model, how to display it, and what interactions it supports. All column configuration happens in PHP - the frontend renders automatically.
Defining Columns
Every table class defines its columns in the columns() method. Use Column::make() for visible columns and Column::data() for hidden data-only columns:
use Forjed\InertiaTable\Column;
Column::make('name', 'Name') // visible column
Column::data('id') // hidden data-only column
Column::data('can_edit', fn ($m) => $m->canEdit()) // computed hidden columnThe first argument is the field name (used for data extraction and as the column identifier). The second is the header label displayed in the table.
Fluent Methods
Columns are configured using chainable fluent methods. These control sorting, visibility, data extraction, and layout:
Column::make('name', 'Name')
->sortable() // allow sorting
->hidden() // include data but don't render
->accessor('users.name') // override DB column for sorting/extraction
->value(fn ($m) => strtoupper($m->name)) // custom value resolver
->fit() // shrink column to content width| Method | Description |
|---|---|
->sortable() | Enables column sorting. See Sorting |
->hidden() | Includes the data in each row but does not render a visible column |
->accessor($field) | Overrides the database column used for sorting and value extraction. Supports dot notation for relationships (e.g. users.name) |
->value(Closure) | Custom value resolver - receives the Eloquent model, returns the display value |
->adjust(Closure) | Transforms the resolved value. Receives the value (not the model), returns the transformed value. See Column Adjusters |
->uppercase() | Convert value to uppercase. See Column Adjusters |
->lowercase() | Convert value to lowercase. See Column Adjusters |
->ucFirst() | Capitalize the first character. See Column Adjusters |
->ucWords() | Capitalize the first character of each word. See Column Adjusters |
->fallback($default) | Replace null values with a default (defaults to 'N/A'). See Column Adjusters |
->fit() | Shrinks the column width to fit its content. Useful for action buttons, status badges, and icons |
Display Modifiers
Display modifiers configure how a cell is rendered. They define the visual representation of the column's data - text, badges, links, icons, and more.
Chain multiple modifiers to compose renderers in a single cell:
Column::make('name', 'Name')
->withIcon('user') // renders icon first
->text() // then text beside it| Modifier | Description |
|---|---|
->text() | Plain text |
->badge($value, $colorField, $variant, $tooltip) | Styled badge with optional colour, variant (string or closure), and tooltip |
->date($value, $format) | Formatted date using the configured or custom format string |
->link($route, $params, $value, $prefetch) | Inertia link with route resolution. See Link Routing |
->copyable() | Click-to-copy with clipboard feedback |
->withIcon($icon, $default) | Icon alongside content - see Icons |
->asIcon($icon, $default) | Icon only (no other displays) - see Icons |
->component($name) | Custom component - see Component Columns |
->enum() | Enum integration (badge with getText/getColor). See Enums |
When no display modifier is specified, the column renders as plain text by default.
Value Convention
All modifiers accepting a $value parameter follow the same convention for resolving what data to display:
| Type | Behaviour |
|---|---|
null | Uses the column's own value |
string | References another field from the row |
Closure | Computed server-side - receives the model, result added to row data |
Column::make('status', 'Status')->badge() // column's own value
Column::make('status', 'Status')->badge('status_label') // different field
Column::make('status', 'Status')->badge(fn ($m) => $m->label) // server-computedThis convention applies to text(), badge(), date(), link(), and copyable().
Relationship Columns (Dot Notation)
Use dot notation in the column name to access values from Eloquent relationships. The package automatically resolves the value through the relation chain:
// Eager-load the relation on your query
ServerTable::make(Server::query()->with('owner'));
// Then use dot notation in your columns
Column::make('owner.name', 'Owner')
Column::make('owner.email', 'Email')
Column::make('owner.address.city', 'City') // multi-levelUnder the hood, Column::make('owner.name', 'Owner') is equivalent to:
Column::make('_owner_name', 'Owner')->accessor('owner.name')The column name is auto-aliased with a _ prefix and underscores (e.g. _owner_name) to avoid conflicts with other columns. The original dot path is used internally for value resolution via Laravel's data_get().
Dot notation works with all column types and the data() factory:
TextColumn::make('owner.name', 'Owner')->sortable()
EnumColumn::make('owner.status', 'Status')
BooleanColumn::make('owner.is_active', 'Active')
Column::data('owner.id') // hidden relation dataTIP
When using dot notation with sortable(), the sort key sent to the database is the dot path (e.g. owner.name). This requires the relation table to be joined in the query - eager loading alone is not sufficient for sorting. Use a beforeQuery hook or add a join to your base query.
Overriding the Accessor
If you need the dot-notation aliasing for the column name but want a different field for value resolution, chain accessor():
Column::make('owner.name', 'Owner')->accessor('custom_field')
// name = '_owner_name', but resolves value from 'custom_field'Slot and Render Prop Names
When overriding cells for dot-notation columns, use the aliased name:
<InertiaTable :table-data="servers">
<template #cell-_owner_name="{ value, row }">
{{ value }}
</template>
</InertiaTable><InertiaTable
tableData={servers}
cellRenderers={{
'_owner_name': ({ value, row }) => <span>{value}</span>
}}
/>Hidden Data Columns
Hidden columns pass data to the frontend without rendering a visible column. This is useful for IDs, permissions, and computed values that your actions or cell overrides need access to:
Column::data('id'),
Column::data('can_delete', fn ($m) => $m->canBeDeleted()),
Column::data('project_id'),Hidden column data is accessible in actions, cell overrides, onRowClick, and anywhere else that receives the row:
<InertiaTable
tableData={servers}
actions={(row) => (
// row.id and row.can_delete are available here
row.can_delete && <button onClick={() => deleteServer(row.id)}>Delete</button>
)}
/><InertiaTable :table-data="servers">
<template #actions="{ row }">
<!-- row.id and row.can_delete are available here -->
<button v-if="row.can_delete" @click="deleteServer(row.id)">Delete</button>
</template>
</InertiaTable>