Skip to content

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:

php
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 column

The 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:

php
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
MethodDescription
->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:

php
Column::make('name', 'Name')
    ->withIcon('user')     // renders icon first
    ->text()               // then text beside it
ModifierDescription
->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:

TypeBehaviour
nullUses the column's own value
stringReferences another field from the row
ClosureComputed server-side - receives the model, result added to row data
php
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-computed

This 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:

php
// 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-level

Under the hood, Column::make('owner.name', 'Owner') is equivalent to:

php
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:

php
TextColumn::make('owner.name', 'Owner')->sortable()
EnumColumn::make('owner.status', 'Status')
BooleanColumn::make('owner.is_active', 'Active')
Column::data('owner.id')  // hidden relation data

TIP

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():

php
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:

template
<InertiaTable :table-data="servers">
    <template #cell-_owner_name="{ value, row }">
        {{ value }}
    </template>
</InertiaTable>
tsx
<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:

php
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:

tsx
<InertiaTable
    tableData={servers}
    actions={(row) => (
        // row.id and row.can_delete are available here
        row.can_delete && <button onClick={() => deleteServer(row.id)}>Delete</button>
    )}
/>
template
<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>