Filters and Clauses
A Filter describes the input users interact with. A Clause describes the comparison to perform. Keeping those responsibilities separate lets one Text Filter offer “contains,” “starts with,” and “equals” without duplicating the input definition.
Start with automatic Filters
Section titled “Start with automatic Filters”Automatic Filters are enabled by default and are created for Columns marked filterable:
InertiaX::table('users') ->data(User::class) ->autoColumns() ->filterableColumns() ->autoFilters();The inferred Column type selects the matching Text, Number, Boolean, Date, DateTime, or Time Filter.
This is a useful starting point. Use filterable() on individual Columns when filtering should be
more selective, and declare an explicit Filter when labels, options, or comparisons are domain
policy.
Built-in Filters
Section titled “Built-in Filters”| Filter | Typical values | Built-in comparisons |
|---|---|---|
TextFilter |
strings | equals, contains, starts/ends with, negations, set/unset |
NumberFilter |
numbers | equals, comparisons, between, set/unset |
BooleanFilter |
booleans | boolean equality and set state |
SelectFilter |
one or many options | selection equality and set state |
DateFilter |
dates | equality, before/after, ranges, set/unset |
DateTimeFilter |
timestamps | date-time comparisons and ranges |
TimeFilter |
times | time comparisons and ranges |
Declare explicit Filters in a reusable Table:
use InertiaX\Components\Table\Filters\BooleanFilter;use InertiaX\Components\Table\Filters\NumberFilter;use InertiaX\Components\Table\Filters\SelectFilter;use InertiaX\Components\Table\Filters\TextFilter;
protected function filters(): array{ return [ TextFilter::make('name', 'Name'), NumberFilter::make('score', 'Score'), BooleanFilter::make('active', 'Active'), SelectFilter::make('status', 'Status')->options([ 'active' => 'Active', 'invited' => 'Invited', ]), ];}Built-in Clauses execute against both Eloquent and Collection sources with equivalent meaning.
Date, datetime, and time Filters accept the exact values emitted by native browser controls:
YYYY-MM-DD, local YYYY-MM-DDTHH:mm[:ss[.SSS]], and HH:mm[:ss[.SSS]]. Laravel normalizes
those values before validation and Eloquent/Collection comparison; malformed or impossible dates
fail instead of being guessed.
Select options
Section titled “Select options”SelectFilter::make('role', 'Role') ->options([ 'admin' => 'Administrator', 'engineer' => 'Engineer', ]) ->multiple();Options can be deferred with a closure. If the callback is source-specific, declare the supported
source kinds through options(..., DataSourceKind::Eloquent) or
supportsOptionSources(...). autoOptions(limit: 200) derives bounded distinct values from the
source; use explicit options when labels or allowed values are domain policy.
When automatic option discovery reaches its limit, the protocol marks the options as truncated and the built-in UI displays an accessible notice. Omitted values are not silently accepted as select options; increase the deliberate bound or provide explicit domain options when the complete set must be selectable.
Change the Clause set
Section titled “Change the Clause set”Filters use the same explicit collection mutations as Tables:
TextFilter::make('name', 'Name') ->removeClause('not_contains') ->defaultClause('contains');Available operations are addClause(), replaceClause(), removeClause(), clearClauses(),
setClauses(), orderClauses(), and defaultClause(). setClauses() means clear then add.
Build a custom comparison
Section titled “Build a custom comparison”Custom Clause identifiers must be namespaced:
use Illuminate\Database\Eloquent\Builder;use InertiaX\Components\Table\Enums\DataSourceKind;use InertiaX\Components\Table\Filters\Clauses\Clause;
TextFilter::make('role', 'Role') ->clearClauses() ->addClause( Clause::make('acme/role-equals', 'Has role') ->validateUsing( fn (mixed $value): bool => is_string($value) && in_array($value, ['Admin', 'Engineer'], true), ) ->applyUsing( fn (Builder $query, string $column, string $value): Builder => $query->where($column, $value), DataSourceKind::Eloquent, ), );validateUsing() validates incoming values. modifyUsing() normalizes a valid value before the
comparison. applyUsing() owns the source operation, and the listed source kinds are mandatory.
If the Clause also supports Collections, provide behavior that is correct for a Collection and
declare DataSourceKind::Collection. Do not claim parity by passing the wrong source type into an
Eloquent callback.
Customize the Filter-level route
Section titled “Customize the Filter-level route”Most customization belongs to Clauses because they own comparison behavior. Use
applyClauseUsing() only when the Filter must route every selected Clause through shared
source-specific behavior:
$filter->applyClauseUsing( function ($source, string $column, mixed $value, Closure $applyClause) { // Cross-cutting Filter behavior, then delegate to the selected Clause. return $applyClause($source, $column, $value); }, DataSourceKind::Eloquent,);This is a localized escape hatch, not the normal way to define a comparison. The selected Clause still owns validation, normalization, capability declarations, and its comparison semantics.
Basic and advanced modes
Section titled “Basic and advanced modes”The default FilterMode::Basic presents the bounded built-in filter experience. Switch the Table
to FilterMode::Advanced when users need recursive groups and explicit Clause selection:
UsersTable::make('users')->filterMode(FilterMode::Advanced)The exact backed strings are accepted too: filterMode('advanced') is equivalent to the enum call.
Invalid strings fail immediately, while protected class defaults remain enum-typed.
Basic mode accepts only one root and group with direct conditions. Nested groups and or are
advanced-mode semantics and are rejected even when state is submitted without the built-in UI.
The server validates all incoming filter state against the emitted definitions before applying it. Advanced filter state is bounded to eight group levels including the root and 100 total condition or child-group nodes, so invalid or excessive input fails before query/Collection execution.