Tailwind Filter Panel Using AlpineJS and Livewire

Tailwind CSS Alpine JS Livewire

Demo

Filters
Loading...

This is a pro component. Get Livewiredemos pro access to view / download the component code.

Livewire Component Class


<?php

namespace App\Http\Livewire;

use Livewire\Component;

class DropdownFilterComponent extends Component
{
    protected $queryString = ['filtersChosen', 'sortByChosen'];



    public array $filterOptions = [
        'brands' => [
            'name' => 'Brands',
            'options' => ['apple'=>'Apple', 'sony' => 'Sony', 'bose' => 'Bose'],
        ],
        'colors' => [
            'name' => 'Color',
            'options' => ['blue' => 'Blue', 'red' => 'Red', 'green' => 'Green','yellow' => 'Yellow'],
        ],
        'types' => [
            'name' => 'Type',
            'options' => ['earbuds' => 'Earbuds', 'earphones' => 'Earphones', 'overhead' => 'Overhead'],
        ]
    ];


    public array $filtersChosen = array();

    public array $filtersToMerge = [
        'brands' => [],
        'colors' => [],
        'types' => [],
    ];

    public array $sortByOptions = ['rating' => 'Best Rating', 'pricedesc'=> 'Price High to Low', 'priceacs' => 'Price Low to Low'];

    public $sortByChosen;

    public function render()
    {
        return view('livewire.dropdown-filter-component');
    }

    public function mount(){
        //Hack to merge query filters with all available filter selectors user can choose from.
        $this->filtersChosen = array_merge($this->filtersToMerge, $this->filtersChosen);
    }

    public function removeFilter($filterType, $filterValue){
        //Remove array element and reindex array
        unset($this->filtersChosen[$filterType][$filterValue]);
        $this->filtersChosen[$filterType] = array_values($this->filtersChosen[$filterType]);
    }

    public function setSortBy($value){
        $this->sortByChosen = $value;
    }

    public function clearSort(){
        $this->sortByChosen = null;
    }

}

Component View File


<div class="relative">
    <!-- DropDowns -->
    <div class="flex bg-white py-3 px-3">
        <div class="flex mr-auto">
        <x-dropdown name="Sort" :options=$sortByOptions panelPosition="right" type="link" livewire-click="setSortBy"/>
        @if(isset($sortByChosen))
        <div class="rounded-full text-sm text-gray-600 border border-gray-400 bg-white my-1 py-1 px-3 mx-2">Sort By : {{$sortByOptions[$sortByChosen]}} <span wire:click="clearSort()" class="ml-2 text-gray-500 font-semibold rounded-full h-4 w-4 px-1 cursor-pointer hover:bg-gray-200">x</span></div>
        @endif
        </div>
        <x-dropdown :name="$filterOptions['brands']['name']" :options="$filterOptions['brands']['options']" panelPosition="left" type="checkbox" wire:model.debounce.0ms="filtersChosen.brands" wire:loading.attr="disabled"/>
        <span class="mx-2 border-r border-gray-300"></span>
        <x-dropdown :name="$filterOptions['colors']['name']" :options="$filterOptions['colors']['options']" panelPosition="left" type="checkbox" wire:model.debounce.0ms="filtersChosen.colors" wire:loading.attr="disabled"/>
        <span class="mx-2 border-r border-gray-300"></span>
        <x-dropdown :name="$filterOptions['types']['name']" :options="$filterOptions['types']['options']" panelPosition="left" type="checkbox" wire:model.debounce.0ms="filtersChosen.types" wire:loading.attr="disabled"/>
    </div>
    <!-- Chosen Filters -->
    <div class="flex items-center bg-gray-100 py-4 px-5">
       <div class="uppercase text-gray-600 text-sm tracking-wide font-semibold">
        Filters
        <span class="mx-2 border-r border-gray-400"></span>
       </div>
        <div class="flex flex-wrap">
           @foreach($filtersChosen as $filterName => $filterValues)
            @foreach($filterValues as $key => $value)
            <div class="rounded-full text-gray-600 border border-gray-400 bg-white my-1 py-1 px-3 mx-2">{{$filterOptions[$filterName]['name']}} : {{$filterOptions[$filterName]['options'][$value]}} <span wire:click="removeFilter('{{$filterName}}', '{{$key}}')" class="ml-2 text-gray-500 font-semibold rounded-full h-4 w-4 px-1 cursor-pointer hover:bg-gray-200">x</span></div>
            @endforeach
           @endforeach
       </div> 
    </div>
    <!--Loading Spinner -->
    <div wire:loading class="absolute text-center left-0 right-0 bottom-12 items-center justify-center">
        <div class="spinner-border animate-spin inline-block w-8 h-8 border-4 rounded-full text-indigo-700" role="status">
          <span class="visually-hidden">Loading...</span>
        </div>
    </div>
</div>

Usage


  @livewire('dropdown-filter-component')

Documentation

This is a an independent filter component, frontend of the component is built using Tailwind and AlpineJS. We are using blade components for the dropdown which you can find here https://livewiredemos.com/component/reusable-dropdown-blade-component-tailwind-and-alpinejs

Once user choses the filter and sort options it gets stored in the Livewire property, that can be further used to filter and sort your eloquent results.