abather / table-filters
table filters
Requires
- php: ^8.2
- filament/filament: ^4.0|^5.0
Requires (Dev)
- laravel/pint: ^1.0
This package is auto-updated.
Last update: 2026-04-06 18:58:58 UTC
README
Table Filters
A fluent builder for Filament table filters. Reduces repetitive filter boilerplate into a single chainable call.
Requirements
- PHP 8.2+
- Filament 4.x or 5.x
Installation
composer require abather/table-filters
Usage
Fluent builder (chained)
Use TableFilters::make(ResourceClass::class) inside your Filament resource's table() method and spread the result into filters().
use Abather\TableFilters\Tables\Filters\TableFilters; public static function table(Table $table): Table { return $table ->filters( TableFilters::make(static::class) ->date() ->numeric('price') ->select('status') ->toggle('is_active') ->relation('category', 'name') ->filters(), ); }
Standalone (individual filters)
Each filter is also available as a static method that returns a plain Filament Filter (or SelectFilter) component — the same object you would get from Filter::make() directly. This means you can chain any method from the Filament filter documentation on top of it, such as ->label(), ->hidden(), ->columnSpan(), ->default(), and so on.
use Abather\TableFilters\Tables\Filters\TableFilters; public static function table(Table $table): Table { return $table ->filters([ // returned as-is TableFilters::dateFilter('created_at', 'Created'), // chain any Filament filter method on top TableFilters::numericFilter('price', 'Price') ->columnSpan(2) ->hidden(fn () => ! auth()->user()->can('filter-prices')), TableFilters::selectFilter(static::class, 'status', 'Status') ->label('Order Status') ->default('active'), TableFilters::toggleFilter('is_active', 'Active'), TableFilters::relationFilter('category', 'name'), TableFilters::relationDateFilter('orders', 'created_at', 'Order Date'), TableFilters::relationNumericFilter('orders', 'total', 'Order Total'), ]); }
Note:
selectFilter()requires the resource class as its first argument because it fetches distinct values from the database automatically.
Available Filters
date() / dateFilter()
Adds a date range filter (or a single date picker).
// chained ->date( field: 'created_at', // column to filter on (default: 'created_at') label: null, // optional label range: true, // true → from/to pickers, false → single picker with_time: false, // use DateTimePicker instead of DatePicker ) // standalone TableFilters::dateFilter(field: 'created_at', label: null, range: true, with_time: false)
numeric() / numericFilter()
Adds a numeric range filter (or an exact-value filter).
// chained ->numeric( field: 'price', label: null, range: true, // true → from/to inputs, false → single input ) // standalone TableFilters::numericFilter(field: 'price', label: null, range: true)
select() / selectFilter()
Adds a select/dropdown filter. When no options are provided, distinct values are pulled from the database automatically.
// chained ->select( field: 'status', label: null, options: null, // array, enum class-string, or null (auto-detect from DB) multiple: false, limit: 10, // max distinct values fetched when options is null ) // standalone — resource class is required as the first argument TableFilters::selectFilter(resource: static::class, field: 'status', label: null, options: null, multiple: false, limit: 10)
toggle() / toggleFilter()
Adds a boolean toggle filter.
// chained ->toggle( field: 'is_active', label: null, default: false, // whether the toggle is on by default negation: false, // when true, filters for false values instead of true ) // standalone TableFilters::toggleFilter(field: 'is_active', label: null, default: false, negation: false)
relation() / relationFilter()
Adds a select filter scoped to a relationship.
// chained ->relation( relationship: 'category', field: 'name', label: null, query: null, // optional Closure to modify the relationship query searchable: true, preload: false, multiple: false, ) // standalone TableFilters::relationFilter(relationship: 'category', field: 'name', label: null, query: null, searchable: true, preload: false, multiple: false)
relationDate() / relationDateFilter()
Adds a date filter scoped to a relationship.
// chained ->relationDate( relationship: 'orders', field: 'created_at', label: null, range: true, with_time: false, ) // standalone TableFilters::relationDateFilter(relationship: 'orders', field: 'created_at', label: null, range: true, with_time: false)
relationNumeric() / relationNumericFilter()
Adds a numeric filter scoped to a relationship.
// chained ->relationNumeric( relationship: 'orders', field: 'total', label: null, range: true, ) // standalone TableFilters::relationNumericFilter(relationship: 'orders', field: 'total', label: null, range: true)
Chaining
All methods return static, so you can chain as many filters as needed:
TableFilters::make(static::class) ->date() ->date('updated_at', 'Updated', range: false) ->numeric('amount', 'Amount', range: false) ->select('status', 'Status', ['draft' => 'Draft', 'published' => 'Published']) ->toggle('featured') ->relation('author', 'name', searchable: true, preload: true) ->relationDate('orders', 'created_at', 'Order Date') ->relationNumeric('orders', 'total', 'Order Total') ->filters()
License
MIT
