Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Livewire Filters Laravel Package

kirschbaum-development/livewire-filters

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require kirschbaum-development/livewire-filters
    php artisan vendor:publish --tag=livewire-filters-views
    

    (Publish views to customize styling; config is optional unless using query strings.)

  2. First Use Case: Filter a Livewire component's data in real-time. For example, in a UserList component:

    use KirschbaumDevelopment\LivewireFilters\Filters;
    
    public $filters = [];
    
    public function mount()
    {
        Filters::add('search', 'text', fn($query) => $query->where('name', 'like', '%'.$this->filters['search'].'%'));
    }
    
    public function render()
    {
        return view('livewire.user-list', [
            'users' => User::query()->apply($this->filters)->get(),
        ]);
    }
    
  3. Add Filter UI:

    <livewire:user-list />
    <livewire:filters wire:model="filters" />
    

Where to Look First

  • Documentation (README is concise and practical).
  • app/Http/Livewire/Filters.php (if published) for config (e.g., query string sync).
  • Published views (resources/views/vendor/livewire-filters/) to customize UI.

Implementation Patterns

Core Workflow

  1. Define Filters: Use Filters::add() in mount() to register filters with:

    • A unique key (e.g., 'search', 'status').
    • Type ('text', 'select', 'date', etc.).
    • A closure to modify the query (e.g., fn($query) => $query->where(...)).
    public function mount()
    {
        Filters::add('status', 'select', fn($query) => $query->where('status', $this->filters['status'] ?? null))
            ->options([
                'active' => 'Active',
                'inactive' => 'Inactive',
            ]);
    }
    
  2. Bind to Livewire Model: Use wire:model="filters" in the <livewire:filters /> component to sync input with the parent component’s $filters property.

  3. Apply Filters: Chain apply($this->filters) to your query in render():

    User::query()->apply($this->filters)->get();
    

Advanced Patterns

  • Dynamic Filter Options: Fetch options from a database or API in updatedFilter hooks:

    public function updatedFilterStatus()
    {
        $this->filters['status_options'] = Status::all()->pluck('name', 'id');
    }
    
  • Multi-Component Filters: Share filters across components by extending a base class or using a trait:

    trait UsesSharedFilters
    {
        public function mount()
        {
            Filters::add('shared_filter', 'text', fn($query) => $query->where(...));
        }
    }
    
  • Reset Filters: Add a button to reset filters via resetFilters():

    <button wire:click="resetFilters">Reset</button>
    
    public function resetFilters()
    {
        $this->reset('filters');
    }
    
  • Query String Sync (if config published): Enable sync_with_query_string: true in config/livewire-filters.php to persist filters in the URL.

Integration Tips

  • Tailwind CSS: Customize published views to match your Tailwind config. Example override:

    <!-- resources/views/vendor/livewire-filters/text.blade.php -->
    <input type="text" class="border-gray-300 rounded-md shadow-sm focus:border-indigo-500">
    
  • Validation: Add validation rules to $rules in your component:

    protected $rules = [
        'filters.search' => 'nullable|string|max:255',
    ];
    
  • Localization: Use Laravel’s localization features for filter labels/placeholders:

    <x-filters.text label="{{ __('Search') }}" placeholder="{{ __('Type to search...') }}" />
    

Gotchas and Tips

Pitfalls

  1. Filter Key Conflicts:

    • Issue: Duplicate filter keys (e.g., two search filters) will overwrite each other.
    • Fix: Use unique keys like user_search or product_search.
  2. Query Application Order:

    • Issue: Closures run in registration order. Later filters may override earlier ones unintentionally.
    • Fix: Order Filters::add() calls logically or use explicit conditions:
      Filters::add('status', 'select', fn($query) => $this->filters['status'] ? $query->where('status', $this->filters['status']) : $query);
      
  3. Performance with Complex Filters:

    • Issue: Heavy filters (e.g., LIKE on large tables) can slow queries.
    • Fix: Add database indexes or use ->take(100) for pagination.
  4. Query String Sync Quirks:

    • Issue: If sync_with_query_string is enabled, filters may not update immediately due to Livewire’s reactivity.
    • Fix: Use wire:ignore on the <livewire:filters /> component or manually trigger updates:
      document.addEventListener('livewire:init', () => {
          Livewire.hook('filter.applied', () => {
              window.location.search = new URLSearchParams(window.livewire?.state?.filters).toString();
          });
      });
      
  5. Published Views Not Updating:

    • Issue: Changes to published views (e.g., resources/views/vendor/livewire-filters/) aren’t reflected.
    • Fix: Clear Laravel’s view cache:
      php artisan view:clear
      

Debugging Tips

  • Log Filter Values: Add a temporary dump in updatedFilter* methods:

    public function updatedFilterSearch()
    {
        \Log::debug('Current filters:', $this->filters);
    }
    
  • Check Query: Log the final query in render():

    \Log::debug('Query:', User::query()->apply($this->filters)->toSql());
    
  • Disable Filters Temporarily: Comment out apply($this->filters) to isolate issues.

Extension Points

  1. Custom Filter Types: Extend the package by creating a new filter component. Example:

    php artisan make:livewire CustomFilter
    

    Then register it in Filters::add():

    Filters::add('custom', 'custom', fn($query) => $query->where(...));
    
  2. Override Default Views: Publish and modify views (e.g., text.blade.php, select.blade.php) to add custom logic like conditional rendering:

    @if($showAdvanced)
        <div class="advanced-filter">{{ $slot }}</div>
    @endif
    
  3. Add Filter Metadata: Attach metadata (e.g., priority, visibility) to filters using a custom trait:

    Filters::add('priority_filter', 'select', fn($query) => $query->where(...))
        ->meta(['priority' => 1, 'visible' => true]);
    
  4. Server-Side Filtering: For large datasets, use cursor-based pagination with filters:

    public function render()
    {
        return User::query()
            ->apply($this->filters)
            ->cursorPaginate(20);
    }
    

Config Quirks

  • Query String Sync:

    • Only works with GET requests. Avoid using it for POST or complex forms.
    • Test with ?filters[search]=test in the URL to verify sync.
  • Default Values: Set defaults in mount():

    public function mount()
    {
        $this->filters = ['status' => 'active'];
    }
    
  • Case Sensitivity: Filter keys in $filters are case-sensitive. Use consistent naming (e.g., camelCase).

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky