Skip to content

feat: add headerFilter() to table columns for inline filter components#19432

Open
leek wants to merge 6 commits intofilamentphp:4.xfrom
leek:feat/header-filters
Open

feat: add headerFilter() to table columns for inline filter components#19432
leek wants to merge 6 commits intofilamentphp:4.xfrom
leek:feat/header-filters

Conversation

@leek
Copy link
Copy Markdown
Contributor

@leek leek commented Mar 5, 2026

CleanShot 2026-03-05 at 12 34 34@2x-optimised

Summary

Adds a new headerFilter() method to table columns, allowing any BaseFilter subclass to render inline under the column header. This provides a richer alternative to searchable(isIndividual: true) — instead of a plain text search input, users can attach select dropdowns, date pickers, custom multi-field schemas, and more directly to column headers.

Examples

// Select filter under column header
TextColumn::make('status')
    ->headerFilter(
        SelectFilter::make('status')
            ->options(OrderStatus::class)
            ->native(false)
    )

// Custom range filter with side-by-side fields
TextColumn::make('price')
    ->headerFilter(
        Filter::make('price')
            ->columns(2)
            ->schema([
                TextInput::make('min')->numeric()->placeholder('Min'),
                TextInput::make('max')->numeric()->placeholder('Max'),
            ])
            ->query(fn (Builder $query, array $data) => $query
                ->when($data['min'] ?? null, fn ($q, $v) => $q->where('price', '>=', $v))
                ->when($data['max'] ?? null, fn ($q, $v) => $q->where('price', '<=', $v))
            )
    )

Design

  • Header filters use a separate Livewire state ($tableHeaderFilters) and form (tableHeaderFiltersForm) — fully isolated from panel filters
  • Always live — applies immediately on change, regardless of deferFilters()
  • Filter field labels are auto-hidden (the column header serves as the label)
  • Multi-field schemas support ->columns() for side-by-side layout with dense gap
  • Fully backwards-compatible — searchable(isIndividual: true) is unchanged
  • Supports filter indicators, reset, session persistence, and records() data sources

Fixes

Fixes #18108
Fixes #15714
Fixes #8879
Fixes #6842

Test Plan

  • Column with SelectFilter renders a select under the header and filters records by exact match
  • Column with custom Filter schema renders inline and applies the custom query
  • searchable(isIndividual: true) still works unchanged
  • Header filter indicators appear and can be removed
  • resetTableFiltersForm() resets header filters
  • Hidden columns' header filters don't apply to the query
  • Hidden filters (->hidden()) don't render in the header row
  • Non-query records() tables receive headerFilters in the callback
  • PHPStan passes with no new errors

Allows attaching any BaseFilter subclass (SelectFilter, Filter with
custom schema, etc.) to a table column via `->headerFilter()`. The
filter renders inline under the column header as a richer alternative
to `searchable(isIndividual: true)`.

- Separate Livewire state ($tableHeaderFilters) and form, isolated
  from panel filters
- Always live (ignores deferFilters())
- Auto-hidden labels, dense gap for multi-field schemas
- Supports indicators, reset, session persistence, records() sources
- Fully backwards-compatible

Fixes filamentphp#18108, filamentphp#15714, filamentphp#8879, filamentphp#6842
@github-project-automation github-project-automation bot moved this to Todo in Roadmap Mar 5, 2026
@leek leek marked this pull request as ready for review March 5, 2026 18:13
@danharrin danharrin added enhancement New feature or request pending review labels Mar 6, 2026
@danharrin danharrin modified the milestone: v4 Mar 6, 2026
Header filters now participate in the main filter system instead of
maintaining a parallel state/form/session/apply pipeline. Removes ~180
lines of duplicated code while preserving all functionality.
@leek leek force-pushed the feat/header-filters branch from 6457769 to fc457e6 Compare March 17, 2026 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request pending review

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants