Skip to content

Defining Tables

Every Table has an ID, a data source, columns, and optional filters or capability overrides. Define it inline when it is local to one response; use a class when the definition is reused, inherited, or large enough to deserve its own file.

The facade creates a lazy Table builder that can be returned directly as an Inertia prop:

use InertiaX\Components\Table\Columns\TextColumn;
use InertiaX\Facades\InertiaX;
return Inertia::render('Users/Index', [
InertiaX::table('users')
->data(User::query())
->addColumn(TextColumn::make('name', 'Name')->sortable()),
]);

Use this style for a small, page-specific Table. The prop name is users, and its protocol component ID is also users. Choose a stable name of 1–64 characters that starts with an ASCII letter and then uses only letters, numbers, _, or -. Laravel rejects invalid names immediately.

app/Tables/ActiveUsersTable.php
<?php
namespace App\Tables;
use App\Models\User;
use InertiaX\Components\Table\Columns\BadgeColumn;
use InertiaX\Components\Table\Columns\NumberColumn;
use InertiaX\Components\Table\Columns\TextColumn;
use InertiaX\Components\Table\Filters\SelectFilter;
use InertiaX\Components\Table\Table;
class ActiveUsersTable extends Table
{
protected static int $defaultPageSize = 25;
protected function data(): mixed
{
return User::query()->where('active', true);
}
protected function columns(): array
{
return [
NumberColumn::make('id', 'ID')->sortable(),
TextColumn::make('name', 'Name')->sortable()->searchable(),
BadgeColumn::make('role', 'Role'),
];
}
protected function filters(): array
{
return [
SelectFilter::make('role', 'Role')->options([
'Admin' => 'Administrator',
'Engineer' => 'Engineer',
]),
];
}
}

Return it by choosing the prop/instance name:

return Inertia::render('Users/Index', [
ActiveUsersTable::make('active_users'),
]);

The class may provide its own protected data() method, or the caller may provide the source:

ActiveUsersTable::make('active_users')->data($query)

A fluent data() call wins over the class declaration. The same per-use precedence applies to columns, filters, and behavior.

Column and filter collections use explicit operations:

ActiveUsersTable::make('users')
->addColumn(TextColumn::make('email', 'Email'))
->replaceColumn(BadgeColumn::make('role', 'Access level'))
->removeColumn('id')
->addFilter(TextFilter::make('email', 'Email'));
  • addColumn() / addFilter() extend the existing declaration.
  • replaceColumn() / replaceFilter() require and replace the matching key.
  • removeColumn() / removeFilter() remove the matching key.
  • clearColumns() / clearFilters() empty the collection.
  • setColumns() / setFilters() are convenience macros for clear then add.

Plural variants accept arrays. They do not weaken duplicate or missing-target validation.

Protected static defaults are inherited and may be overridden by a child class or a fluent call:

use InertiaX\Components\Table\Enums\FilterMode;
use InertiaX\Components\Table\Enums\SelectionMode;
protected static int $defaultPageSize = 25;
protected static array $defaultPageSizeOptions = [10, 25, 50];
protected static bool $defaultPagination = true;
protected static bool $defaultSorting = true;
protected static bool $defaultMultiSort = true;
protected static bool $defaultSelection = false;
protected static SelectionMode $defaultSelectionMode = SelectionMode::Multiple;
protected static bool $defaultAutoColumns = false;
protected static bool $defaultAutoFilters = true;
protected static FilterMode $defaultFilterMode = FilterMode::Basic;
protected static bool $defaultRefreshButton = true;

Column-wide defaults are also available: $defaultSortableColumns, $defaultCopyableColumns, $defaultSearchableColumns, $defaultToggleableColumns, $defaultVisibleColumns, $defaultWrapColumns, $defaultTruncateColumns, and $defaultFilterableColumns.

Prefer per-column capability calls when only a few fields need the behavior. Use class defaults when the policy genuinely applies to the entire Table family.

Every Table needs a distinct ID and matching prop:

return Inertia::render('Dashboard', [
ActiveUsersTable::make('active_users'),
AuditEventsTable::make('audit_events'),
]);
<InertiaX prop="active_users" />
<InertiaX prop="audit_events" />

State is namespaced by Table ID, preventing pagination, filters, or requests from colliding.