Skip to content

Column Filters โ€‹

Introduction โ€‹

A column filter narrows rows by that column's value. Register filters in filters() and chain configuration methods on the Filter facade.

For a header-wide search, see Search Input. For AND / OR conditions on top of these filters, see Filter Builder.

If the column is a Custom Field or comes from a relationship, map the database field so filtering can run. See Working With Custom Fields and Relationship-Based Columns.

Enabling Filters โ€‹

Return Filter definitions from filters(). The first argument is the column field; the optional second argument is the database field when it differs.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::inputText('name')->placeholder('Product Name'),

            Filter::boolean('in_stock')->label('In Stock', 'Out of Stock'),

            Filter::number('price_BRL', 'price')
                ->thousands('.')
                ->decimal(','),
        ];
    }
}

Filter Position โ€‹

ValueBehavior
inlineFilters inside the table. Updates are live and debounced.
dropdownA popover anchored to a Filter button. Edits stay in a draft until Apply.
flyoutA drawer from the left or right edge. Edits stay in a draft until Apply.
nullNo filter UI.

The v6 value outside is gone. Use dropdown or flyout.

Per table, set the config in boot():

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;

class ProductTable extends PowerGridComponent
{
    public function boot(): void
    {
        config(['livewire-powergrid.filter' => 'flyout']);
    }
}

Global default: Filter Position.

When filter is flyout, filter_flyout controls the drawer (position left or right, close_on_escape, close_on_click_outside). Override those keys the same way in boot().

In dropdown and flyout, chain order(int $order) on a filter to set panel order. Otherwise PowerGrid uses the filters() array index. Inline filters ignore order().

Draft and Apply โ€‹

Dropdown and flyout never filter live. Edits land in draftFilters and commit when the user presses Apply (applyFilters()). Reset restores the last committed state.

The bag is field-keyed: draftFilters.{field}.value (and .op, .value.start, .value.end, .value.formatted as needed). When the field contains a dot (for example products.diet), the key is the column name instead (diet).

phptests/Feature/ProductTableTest.php
Livewire::test(ProductTable::class)
    ->set('draftFilters.name.value', 'pizza')
    ->call('applyFilters')
    ->assertSee('Pizza');

Date ranges use Flatpickr's formatted string on the field key:

php
->set('draftFilters.created_at.value.formatted', '2024-01-01 to 2024-12-31')
->call('applyFilters');

Filter Wire โ€‹

Livewire modifiers come from config('livewire-powergrid.filter_wire'), merged over the defaults in Support\FilterWire. Override per table with filterWire():

phpapp/Livewire/ProductTable.php
public function filterWire(): array
{
    return [
        'input_text' => ['value' => 'live.debounce.800ms'],
    ];
}

Slots: value, operator, start, end, formatted. See Filter Wire.

Expand or Collapse the Filter Panel โ€‹

With flyout, $showFilters controls whether the drawer is open. Set it to true to start with the drawer open. The dropdown popover keeps its open state in the browser and ignores $showFilters.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;

class ProductTable extends PowerGridComponent
{
    public bool $showFilters = true;
}

Standard Filters โ€‹

Text Filter โ€‹

Text input plus an operator dropdown. All operators are enabled by default. operators() always keeps contains in the list.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
       Filter::inputText('name', 'name')
          ->operators(['contains', 'is', 'is_not'])
          ->placeholder('Product name'),
    ];
}
MethodDescription
operators(array $operators)Enabled search operators
placeholder(string $placeholder)Input placeholder

Operators: contains, contains_not, is, is_not, starts_with, ends_with, is_empty, is_not_empty, is_null, is_not_null, is_blank, is_not_blank.

Number Filter โ€‹

Min / max inputs against a numeric column.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::number('price')
            ->thousands('.')
            ->decimal(',')
            ->placeholder('Min', 'Max'),
    ];
}
MethodDescription
thousands(string $thousands)Thousands separator
decimal(string $decimal)Decimal separator
placeholder(string $min, string $max)Placeholders for the min/max inputs

Boolean Filter โ€‹

Dropdown with All, true, and false. Default labels are Yes / No.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::boolean('in_stock')
            ->label('yes', 'no'),
    ];
}

label(string $trueLabel, string $falseLabel) sets the true and false option labels.

Select Filter โ€‹

Single-select dropdown from a datasource.

phpapp/Livewire/ProductTable.php
use App\Models\Category;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::select('category_name', 'category_id')
            ->datasource(Category::all())
            ->optionLabel('name')
            ->optionValue('id'),
    ];
}
MethodDescription
datasource(Collection|array|Closure $collection)Options source
computedDatasource(string $method)Name of a computed property that returns options
optionValue(string $value)Option value field
optionLabel(string $value)Option label field
depends(array $fields)Parent filter fields. See Dependent Filters

Multi-Select Filter โ€‹

Multi-select dropdown from a datasource.

Tom Select and Slim Select are not bundled. Install one, expose it on window, and set plugins.select.default to tom or slim (Slim Select is the config default). See TomSelect and SlimSelect.

phpapp/Livewire/ProductTable.php
use App\Models\Category;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::multiSelect('category_name', 'category_id')
            ->datasource(Category::all())
            ->optionValue('id')
            ->optionLabel('name'),
    ];
}
MethodDescription
datasource(Collection|array|Closure $collection)Options source
optionValue(string $value)Option value field
optionLabel(string $value)Option label field
depends(array $fields)Parent filter fields

Multi-Select Async Filter โ€‹

Same UI as Multi-Select, loading options from an HTTP endpoint. Requires Tom Select (plugins.select.default = tom). See TomSelect.

php
use PowerComponents\LivewirePowerGrid\Facades\Filter;
use PowerComponents\LivewirePowerGrid\PowerGridComponent;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::multiSelectAsync('category_name', 'category_id')
                ->url(route('category.index'))
                ->method('POST')
                ->parameters(['active' => 1])
                ->optionValue('id')
                ->optionLabel('name'),
        ];
    }
}
php
use App\Http\Controllers\Api\CategorySearch;

Route::post('category', CategorySearch::class)->name('category.index');
php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Category;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class CategorySearch extends Controller
{
    public function __invoke(Request $request): Collection
    {
        return Category::query()
            ->select('id', 'name')
            ->orderBy('name')
            ->when($request->search,
                fn (Builder $query) => $query
                    ->where('name', 'like', "%{$request->search}%")
            )
            ->get();
    }
}
MethodDescription
url(string $url)Endpoint that returns options
method(string $method = 'get')HTTP method
parameters(array $parameters)Extra request payload (POST) or query string (GET)
optionValue(string $value)Option value field
optionLabel(string $label)Option label field

The typed text is sent as search, so don't use search as a key in parameters().

Enum Select Filter โ€‹

Dropdown from a PHP Enum. To show labels instead of case values, implement labelTurbineFilter() on the enum.

php
use App\Enums\Diet;
use PowerComponents\LivewirePowerGrid\Column;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::enumSelect('diet', 'products.diet') 
                ->datasource(Diet::cases()),
        ];
    }

    public function columns(): array
    {
        return [
            Column::make('Diet', 'diet', 'products.diet') 
            //...
        ];
    }
}
php
enum Diet: int
{
    case ALL      = 0;
    case VEGAN    = 1;
    case CELIAC   = 2;

    public function labels(): string
    {
        return match ($this) {
            self::ALL         => "๐Ÿฝ๏ธ All diets",
            self::VEGAN       => "๐ŸŒฑ Suitable for Vegans",
            self::CELIAC      => "๐Ÿฅœ Suitable for Celiacs",
        };
    }

    public function labelTurbineFilter(): string
    {
        return $this->labels();
    }
}
MethodDescription
datasource(Collection|array $enumCases)Enum cases
optionValue(string $value)Option value field (default value)
optionLabel(string $value)Option label field

Datetime Picker Filter โ€‹

Flatpickr datetime range. Flatpickr is not bundled โ€” install it and import its assets. See Configuring Flatpickr.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::datetimepicker('produced_at_formatted', 'produced_at')
            ->params([
                'timezone' => 'America/Sao_Paulo',
            ]),
    ];
}

params(array $params) is merged into Flatpickr's config (enableTime is already true for datetime). Extra PowerGrid keys:

ParameterValueDescription
only_futureboolDisallow selecting dates in the past.
no_weekendsboolDisallow selecting weekend dates.
timezonetimezoneParse the selected range in this timezone.

Date Picker Filter โ€‹

Same as Datetime Picker, without time.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::datepicker('creation_date_formatted', 'creation_date'),
    ];
}

Dynamic Filter โ€‹

Render an external Blade / Livewire component as the filter control (for example WireUI). Bind it to a filters.* path in attributes(). PowerGrid does not apply a dynamic type to the query โ€” read that path in datasource(), or use a standard filter with builder().

phpapp/Livewire/ProductTable.php
use Illuminate\Database\Eloquent\Builder;
use App\Models\Product;

public function datasource(): Builder
{
    return Product::query()
        ->when(
            data_get($this->filters, 'dynamic.in_stock'),
            fn (Builder $query, $value) => $query->where('in_stock', $value)
        );
}
phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::dynamic('in_stock', 'in_stock')
                ->component('select')
                ->attributes([
                    'class'            => 'min-w-[170px]',
                    'async-data'       => route('categories.index'),
                    'option-label'     => 'name',
                    'multiselect'      => false,
                    'option-value'     => 'id',
                    'placeholder'      => 'Test',
                    'wire:model.live'  => 'filters.dynamic.in_stock',
                ]),
        ];
    }
}
MethodDescription
component(string $component)Component to render
attributes(array $attributes)Attributes passed to the component

Dependent Filters โ€‹

depends() lists parent filter keys (the parent's field, or its column name when the field contains a dot). The child datasource() closure receives the current parent values, keyed the same way.

phpapp/Livewire/ProductTable.php
use Illuminate\Database\Eloquent\Builder;
use PowerComponents\LivewirePowerGrid\Facades\Filter;
use PowerComponents\LivewirePowerGrid\PowerGridComponent;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::select('category_name', 'category_id')
                ->datasource(Category::all())
                ->optionLabel('name')
                ->optionValue('id'),

            Filter::select('product_name', 'products.id')
                ->depends(['category_id']) 
                ->datasource(
                    fn ($depends) => Product::query()
                        ->when(
                            isset($depends['category_id']),
                            fn (Builder $query) => $query->where('category_id', $depends['category_id'])
                        )
                        ->get()
                )
                ->optionLabel('name')
                ->optionValue('id'),
        ];
    }
}

Custom Filter Query โ€‹

Override how a filter hits the query with builder() (Eloquent / Query Builder) or collection() (Collections).

phpapp/Livewire/ProductTable.php
use Illuminate\Database\Eloquent\Builder;
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::boolean('calories')
                ->label('Caloric', 'Light')
                ->builder(function (Builder $query, string $value) {
                    $q = match ($value) {
                        default => ['operator' => '>=', 'calories' => 0],
                        'true'  => ['operator' => '>=', 'calories' => 300],
                        'false' => ['operator' => '<', 'calories' => 300],
                    };

                    return $query->where('calories', $q['operator'], $q['calories']);
                }),
        ];
    }
}
phpapp/Livewire/ProductTable.php
use Illuminate\Support\Collection;

->collection(function (Collection $collection, mixed $value) {
    return $collection->where('some_field', '!=', $value);
})

For a modal that composes several of these filters with AND / OR, see Filter Builder.

Filter by Relationship โ€‹

Use filterRelation() with the relation name and the related field.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::inputText('category_name')
                ->filterRelation('category', 'name'),
        ];
    }
}

Default Filter Values โ€‹

default() applies when the table mounts.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\Facades\Filter;

public function filters(): array
{
    return [
        Filter::select('category_name', 'category_id')
            ->datasource(Category::all())
            ->optionLabel('name')
            ->optionValue('id')
            ->default(1), 

        Filter::boolean('in_stock')
            ->label('In Stock', 'Out of Stock')
            ->default(true), 

        Filter::inputText('name')
            ->default(['value' => 'Pizza', 'operator' => 'contains']),

        Filter::number('price', 'price')
            ->default(['start' => 100, 'end' => 500]),

        Filter::datepicker('production_date', 'production_date')
            ->default(['start' => '2024-01-01', 'end' => '2024-12-31']),
    ];
}
Filter typeDefault value
selectSingle value matching optionValue
multiSelectArray of values
booleantrue or false
inputTextString, or ['value' => โ€ฆ, 'operator' => โ€ฆ]
numberNumber (start only), or ['start' => โ€ฆ, 'end' => โ€ฆ]
datepicker / datetimepicker['start' => โ€ฆ, 'end' => โ€ฆ] (formatted optional)

Custom Components โ€‹

Replace a standard filter's markup with component($view, $attributes = []). The view receives your attributes merged with the filter definition. Bind your input with $attributes->get('wire')['value'], the same wire:model the built-in control uses.

phpapp/Livewire/ProductTable.php
use PowerComponents\LivewirePowerGrid\PowerGridComponent;
use PowerComponents\LivewirePowerGrid\Facades\Filter;

class ProductTable extends PowerGridComponent
{
    public function filters(): array
    {
        return [
            Filter::boolean('in_stock')
                ->component('my-custom-select', [
                    'class' => 'p-2',
                ]),
        ];
    }
}
phpresources/views/components/my-custom-select.blade.php
<select class="{{ $attributes->get('class') }}" {{ $attributes->get('wire')['value'] }}>
    <option value="all">All</option>
    <option value="true">{{ $attributes->get('trueLabel') }}</option>
    <option value="false">{{ $attributes->get('falseLabel') }}</option>
</select>

Created By Luan Freitas and @DanSysAnalyst