Recipes
These recipes build on Your first Table. Each keeps source behavior in Laravel and presentation behavior in React.
Refine the automatic User Table
Section titled “Refine the automatic User Table”Start from the inferred Table in the quick start and explicitly add only the fields whose presentation is part of your domain. Bulk inference skips those existing keys:
InertiaX::table('users') ->data(User::class) ->autoColumns() ->filterableColumns() ->autoFilters() ->addColumn( TextColumn::make('name', 'Full name') ->searchable() ->sortable() ->filterable(), ) ->addColumn( TextColumn::make('email', 'Email address') ->searchable() ->filterable() ->copyable(), );This preserves automatic inference for the remaining allowed model fields. Move to a fully
explicit columns() declaration when the whole Table becomes intentional application UI.
Searchable, sortable Eloquent Table
Section titled “Searchable, sortable Eloquent Table”InertiaX::table('users') ->data(User::query()->whereBelongsTo($account)) ->addColumns([ NumberColumn::make('id', 'ID')->sortable(), TextColumn::make('name', 'Name')->sortable()->searchable(), TextColumn::make('email', 'Email')->searchable(), BadgeColumn::make('status', 'Status'), ]) ->pageSize(25) ->pageSizeOptions([10, 25, 50]);Only the marked Columns participate in search and sorting. Tenant scoping remains part of the base query.
Collection-backed activity feed
Section titled “Collection-backed activity feed”AuditEventsTable::make('audit_events') ->data(collect($events)) ->rowKey('event_id') ->pageSize(20);Use this for an already-bounded domain result. For a large database dataset, pass an Eloquent builder so pagination and comparisons stay in SQL.
Status filter with labels
Section titled “Status filter with labels”BadgeColumn::make('status', 'Status') ->variant([ 'active' => 'success', 'invited' => 'secondary', 'blocked' => 'destructive', ]) ->filterable() ->filter( SelectFilter::make('status', 'Status')->options([ 'active' => 'Active', 'invited' => 'Invited', 'blocked' => 'Blocked', ]), );The stored values remain stable while the cell and filter expose user-facing presentation.
Single-row selection
Section titled “Single-row selection”use InertiaX\Components\Table\Enums\SelectionMode;
UsersTable::make('users') ->selection() ->selectionMode(SelectionMode::Single);<InertiaX prop="users" table={{ events: { selectionChange({ selection }) { setSelectedUserId(selection[0]); }, }, }}/>The event reports row IDs. Fetch or authorize any domain operation independently on the server.
Two Tables on a dashboard
Section titled “Two Tables on a dashboard”return Inertia::render('Dashboard', [ ActiveUsersTable::make('active_users')->data(User::query()->where('active', true)), AuditEventsTable::make('audit_events')->data($auditEvents),]);<> <section> <h2>Active users</h2> <InertiaX prop="active_users" /> </section> <section> <h2>Audit events</h2> <InertiaX prop="audit_events" /> </section></>The application-level provider from Installation already owns both Tables. Distinct IDs isolate URL keys, partial reloads, and request ordering.
Page-specific override of a shared Table
Section titled “Page-specific override of a shared Table”ActiveUsersTable::make('users') ->data(User::query()->where('active', true)) ->addColumn(TextColumn::make('email', 'Email')->copyable()) ->replaceColumn(BadgeColumn::make('role', 'Access level')) ->pageSize(50);The base class stays reusable; the caller makes its difference explicit.
Infer one model field
Section titled “Infer one model field”protected function columns(): array{ return [ TextColumn::make('name', 'Name')->searchable(), AutoColumn::make('score', 'Score')->sortable(), DateTimeColumn::make('last_seen_at', 'Last seen')->sortable(), ];}AutoColumn infers the named Eloquent field while preserving the capabilities chained onto it.
Localized empty state
Section titled “Localized empty state”function EmptyUsers({ colSpan }: TableStateRegionProps) { return ( <tr> <td colSpan={colSpan} className="py-12 text-center"> No users match these filters. </td> </tr> );}
<InertiaX prop="users" table={{ regions: { emptyState: EmptyUsers } }} />This replaces only the empty row. Search, filters, requests, pagination, and the rest of the built-in renderer remain intact.
Maintained example applications
Section titled “Maintained example applications”The canonical repository keeps three examples with deliberately different roles:
- The Laravel workbench covers inline data, Eloquent, Collections, reusable classes, all built-in types, custom full-stack leaf types, multiple Tables, and real Inertia request round trips. It is the compatibility evidence.
- The interactive demo source has
User inference, explicit Order definitions, and a Collection activity feed as the stable
#/users,#/orders, and#/auditscreens. It executes deterministic browser fixtures and says so prominently; it is not Laravel, Eloquent, database, or Inertia evidence. - The React renderer lab is an internal conformance surface for direct envelopes, renderer customization, registered custom cells, and diagnosed fallback—not a customer demo.