Skip to content

Pro Component — This trait requires an Aura UI Pro license.

Overview

The WithAuraFilters trait adds a comprehensive filtering system to any Livewire component. It manages filter state, provides active filter badge display, and integrates with the <x-aura::data-table> component. Supports multiple filter types including select dropdowns, date ranges, booleans, and text search. Filters are applied to your Eloquent query automatically.

Installation

Add the trait to your Livewire component:

use BlueStarSystem\AuraUIPro\Traits\WithAuraFilters;
use Livewire\Component;

class ProductCatalog extends Component
{
    use WithAuraFilters;

    // ...
}

Required Methods

filters(): array

Define the available filters. Each filter is an associative array describing its type, label, and options.

public function filters(): array
{
    return [
        [
            'key' => 'status',
            'label' => 'Status',
            'type' => 'select',
            'options' => [
                '' => 'All Statuses',
                'active' => 'Active',
                'inactive' => 'Inactive',
                'pending' => 'Pending',
            ],
        ],
        [
            'key' => 'created_at',
            'label' => 'Created Date',
            'type' => 'date-range',
        ],
        [
            'key' => 'featured',
            'label' => 'Featured Only',
            'type' => 'boolean',
        ],
        [
            'key' => 'search',
            'label' => 'Search',
            'type' => 'search',
            'placeholder' => 'Search by name...',
        ],
    ];
}

Filter Types

Select

Renders a dropdown with predefined options.

[
    'key' => 'category',
    'label' => 'Category',
    'type' => 'select',
    'options' => [
        '' => 'All Categories',
        'electronics' => 'Electronics',
        'clothing' => 'Clothing',
        'books' => 'Books',
    ],
]

Date Range

Renders two date inputs (from and to) for filtering a date column.

[
    'key' => 'created_at',
    'label' => 'Date Range',
    'type' => 'date-range',
]

The trait stores date range values as $filterValues['created_at_from'] and $filterValues['created_at_to'].

Boolean

Renders a toggle/checkbox for true/false filtering.

[
    'key' => 'is_active',
    'label' => 'Active Only',
    'type' => 'boolean',
]

Renders a text input for partial-match filtering on a specific field.

[
    'key' => 'name_search',
    'label' => 'Name',
    'type' => 'search',
    'placeholder' => 'Search by name...',
    'column' => 'name', // Database column to search against
]

Provided Properties

Property Type Default Description
filterValues array [] Current filter values keyed by filter key.
showFilters bool false Whether the filter sidebar/panel is visible.

Provided Methods

Method Description
toggleFilters() Show or hide the filter panel.
applyFilter(string $key, mixed $value) Set a filter value programmatically.
resetFilter(string $key) Reset a single filter to its default value.
resetAllFilters() Reset all filters to their default values.
getActiveFilters(): array Returns array of currently active filters with their labels and values.
applyFiltersToQuery(Builder $query): Builder Apply all active filters to an Eloquent query.

Blade Integration

The filter UI is rendered via dedicated Blade directives within your component view:

<!-- resources/views/livewire/product-catalog.blade.php -->
<div>
    <div class="mb-4 flex items-center justify-between">
        <h1 class="text-xl font-bold">Products</h1>
        <x-aura::button variant="ghost" wire:click="toggleFilters" size="sm">
            <x-aura::icon name="funnel" class="h-4 w-4 mr-1" />
            Filters
            @if(count($this->getActiveFilters()) > 0)
                <x-aura::badge size="sm" variant="primary" class="ml-1">
                    {{ count($this->getActiveFilters()) }}
                </x-aura::badge>
            @endif
        </x-aura::button>
    </div>

    {{-- Active filter badges --}}
    @if(count($this->getActiveFilters()) > 0)
        <div class="mb-4 flex flex-wrap gap-2">
            @foreach($this->getActiveFilters() as $filter)
                <x-aura::badge variant="info" size="sm">
                    {{ $filter['label'] }}: {{ $filter['displayValue'] }}
                    <button wire:click="resetFilter('{{ $filter['key'] }}')" class="ml-1">
                        <x-aura::icon name="x-mark" class="h-3 w-3" />
                    </button>
                </x-aura::badge>
            @endforeach
            <button wire:click="resetAllFilters" class="text-sm text-gray-500 hover:text-gray-700">
                Clear all
            </button>
        </div>
    @endif

    {{-- Filter sidebar --}}
    @if($showFilters)
        <div class="mb-6 rounded-lg border bg-white p-4 shadow-sm">
            <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
                @foreach($this->filters() as $filter)
                    @if($filter['type'] === 'select')
                        <x-aura::select
                            :label="$filter['label']"
                            :options="$filter['options']"
                            wire:model.live="filterValues.{{ $filter['key'] }}"
                        />
                    @elseif($filter['type'] === 'boolean')
                        <x-aura::toggle
                            :label="$filter['label']"
                            wire:model.live="filterValues.{{ $filter['key'] }}"
                        />
                    @elseif($filter['type'] === 'search')
                        <x-aura::input
                            :label="$filter['label']"
                            :placeholder="$filter['placeholder'] ?? 'Search...'"
                            wire:model.live.debounce.300ms="filterValues.{{ $filter['key'] }}"
                        />
                    @elseif($filter['type'] === 'date-range')
                        <div class="col-span-2 grid grid-cols-2 gap-2">
                            <x-aura::date-picker
                                label="{{ $filter['label'] }} From"
                                wire:model.live="filterValues.{{ $filter['key'] }}_from"
                            />
                            <x-aura::date-picker
                                label="{{ $filter['label'] }} To"
                                wire:model.live="filterValues.{{ $filter['key'] }}_to"
                            />
                        </div>
                    @endif
                @endforeach
            </div>
        </div>
    @endif

    {{-- Table content --}}
    <x-aura::data-table :columns="$this->columns()" :rows="$this->getRows()">
        {{-- Row rendering --}}
    </x-aura::data-table>
</div>

Examples

Product Catalog Filters

<?php

namespace App\Livewire;

use App\Models\Product;
use BlueStarSystem\AuraUIPro\Traits\WithAuraDataTable;
use BlueStarSystem\AuraUIPro\Traits\WithAuraFilters;
use Livewire\Component;

class ProductCatalog extends Component
{
    use WithAuraDataTable;
    use WithAuraFilters;

    public function columns(): array
    {
        return [
            ['key' => 'name', 'label' => 'Product', 'sortable' => true, 'searchable' => true],
            ['key' => 'category', 'label' => 'Category', 'sortable' => true],
            ['key' => 'price', 'label' => 'Price', 'sortable' => true, 'format' => 'currency'],
            ['key' => 'stock', 'label' => 'Stock', 'sortable' => true],
            ['key' => 'status', 'label' => 'Status', 'sortable' => true],
        ];
    }

    public function filters(): array
    {
        return [
            [
                'key' => 'category',
                'label' => 'Category',
                'type' => 'select',
                'options' => [
                    '' => 'All Categories',
                    ...Category::pluck('name', 'slug')->toArray(),
                ],
            ],
            [
                'key' => 'status',
                'label' => 'Status',
                'type' => 'select',
                'options' => [
                    '' => 'All',
                    'active' => 'Active',
                    'draft' => 'Draft',
                    'archived' => 'Archived',
                ],
            ],
            [
                'key' => 'in_stock',
                'label' => 'In Stock Only',
                'type' => 'boolean',
            ],
            [
                'key' => 'created_at',
                'label' => 'Created',
                'type' => 'date-range',
            ],
        ];
    }

    public function query(): \Illuminate\Database\Eloquent\Builder
    {
        $query = Product::query();

        // Apply all filters at once
        return $this->applyFiltersToQuery($query);
    }

    public function render()
    {
        return view('livewire.product-catalog');
    }
}

Custom Filter Application

If you need custom logic for specific filters, override how they are applied:

public function query(): \Illuminate\Database\Eloquent\Builder
{
    $query = Product::query()->with('category');

    // Apply standard filters
    $query = $this->applyFiltersToQuery($query);

    // Custom filter logic
    if (!empty($this->filterValues['price_min'])) {
        $query->where('price', '>=', $this->filterValues['price_min']);
    }

    if (!empty($this->filterValues['price_max'])) {
        $query->where('price', '<=', $this->filterValues['price_max']);
    }

    return $query;
}

Combining with WithAuraDataTable

The traits are designed to work together. When combined, the filter values automatically integrate with the data table's query pipeline:

class OrderManager extends Component
{
    use WithAuraDataTable;
    use WithAuraFilters;

    public function columns(): array
    {
        return [
            ['key' => 'number', 'label' => 'Order #', 'sortable' => true],
            ['key' => 'customer', 'label' => 'Customer', 'sortable' => true],
            ['key' => 'total', 'label' => 'Total', 'sortable' => true],
            ['key' => 'status', 'label' => 'Status', 'sortable' => true],
        ];
    }

    public function filters(): array
    {
        return [
            ['key' => 'status', 'label' => 'Status', 'type' => 'select', 'options' => [
                '' => 'All', 'pending' => 'Pending', 'processing' => 'Processing',
                'shipped' => 'Shipped', 'delivered' => 'Delivered',
            ]],
            ['key' => 'created_at', 'label' => 'Order Date', 'type' => 'date-range'],
        ];
    }

    public function query(): \Illuminate\Database\Eloquent\Builder
    {
        return $this->applyFiltersToQuery(Order::query()->with('customer'));
    }
}

Live Demo

27" Monitor Stand Electronics $45.00 73 Active
Bamboo Cutting Board Home $22.00 168 Active
Bath Towel Set Home $34.99 110 Active
Bluetooth Speaker Electronics $42.99 165 Active
Canvas Sneakers Clothing $44.50 156 Active
Cargo Pants Clothing $54.99 88 Active
Ceramic Vase Home $32.99 67 Active
Clean Code Books $39.99 340 Active
Cotton T-Shirt Clothing $24.99 500 Draft
Cycling Gloves Sports $22.50 155 Active

Accessibility

  • The filter toggle button includes an aria-expanded attribute reflecting the panel visibility.
  • Filter inputs use standard Aura UI form components which provide proper label associations.
  • Active filter badges include remove buttons with aria-label="Remove [filter name] filter".
  • The "Clear all" button has aria-label="Clear all active filters".
  • Filter changes trigger an aria-live="polite" announcement of the updated result count.
  • The filter panel is focusable and can be closed with Escape when implemented as a slide-over.
  • Date range inputs are properly labeled as "From" and "To" for screen readers.