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

Searchable Select Laravel Package

williamug/searchable-select

Feature-rich searchable select for Laravel Livewire 3/4, powered by Alpine.js and styled with Tailwind. Supports single and multi-select, grouped options, cascading dropdowns, clear button, dark mode, accessibility, and real-time client-side search.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation: Run composer require williamug/searchable-select and ensure Tailwind CSS is configured to scan the package views (see Tailwind CSS Setup).
  2. First Use Case: Bind a Livewire property to the component using wire:model with a simple Eloquent collection or array of options.
    <x-searchable-select
        wire:model="country_id"
        :options="$countries"
        placeholder="Select a country"
    />
    
  3. Verify: Ensure the dropdown appears, filters as you type, and updates the Livewire property on selection.

Where to Look First

  • Quick Start: Follow the Basic Single Select example in the README.
  • Props Reference: Check the Component Props Reference for available customizations.
  • Tailwind Setup: Confirm your tailwind.config.js or CSS file includes the package’s views (critical for styling).

Implementation Patterns

Core Workflow

  1. Data Preparation:

    • Fetch data in your Livewire component’s mount() method (e.g., Country::all()).
    • Pass the collection/array to the component via :options.
    public function mount() {
        $this->countries = Country::orderBy('name')->get();
    }
    
  2. Binding:

    • Use wire:model to bind to a Livewire property (no need for :selected-value).
    • The component automatically handles two-way sync via $wire.entangle().
  3. Validation:

    • Validate the bound property in Livewire methods (e.g., save()).
    public function save() {
        $this->validate(['country_id' => 'required|exists:countries,id']);
    }
    
  4. Rendering:

    • Place the component in your Blade view with labels, error messages, and other UI elements.
    <label for="country">Country</label>
    <x-searchable-select
        wire:model="country_id"
        :options="$countries"
        placeholder="Select..."
    />
    @error('country_id') <span>{{ $message }}</span> @enderror
    

Integration Tips

Multi-Select Patterns

  • Use an array property for wire:model (e.g., public $selected_skills = [];).
  • Enable multi-select with :multiple="true".
  • Display selected items dynamically:
    @if(!empty($selected_skills))
        <div class="mt-2">
            Selected: {{ count($selected_skills) }} skills
        </div>
    @endif
    

Dependent Dropdowns

  1. Parent-Child Relationships:
    • Use updatedPropertyName() in Livewire to reload child options when a parent changes.
    public function updatedCountryId($value) {
        $this->regions = Region::where('country_id', $value)->get();
        $this->region_id = null; // Reset child selection
    }
    
  2. Conditional Disabling:
    • Disable child dropdowns until their parent is selected:
    <x-searchable-select
        wire:model="region_id"
        :options="$regions"
        :disabled="!$country_id"
    />
    

Grouped Options

  • Structure your data as an array of groups:
    $groupedOptions = [
        ['label' => 'North America', 'options' => [...]],
        ['label' => 'Europe', 'options' => [...]],
    ];
    
  • Enable grouping with :grouped="true" and customize group labels:
    <x-searchable-select
        :options="$groupedOptions"
        :grouped="true"
        group-label="label"
        group-options="options"
    />
    

Custom Keys

  • Override default optionValue/optionLabel for non-standard data structures:
    <x-searchable-select
        :options="$countries"
        option-value="code"
        option-label="country_name"
    />
    

Gotchas and Tips

Pitfalls

  1. Tailwind Purging:

    • Issue: Dropdown appears unstyled or invisible.
    • Fix: Ensure tailwind.config.js includes the package’s views:
      content: [
          './resources/**/*.blade.php',
          './vendor/williamug/searchable-select/resources/views/**/*.blade.php',
      ],
      
    • Rebuild assets after updating the config.
  2. Livewire Property Mismatch:

    • Issue: Selected value doesn’t update or validation fails.
    • Fix: Verify wire:model matches the Livewire property name exactly (case-sensitive).
  3. Empty Options Handling:

    • Issue: Dropdown shows no results even with data.
    • Fix: Check for empty collections/arrays and set a placeholder:
      <x-searchable-select
          :options="$countries"
          placeholder="No countries found"
      />
      
  4. Multi-Select Array Initialization:

    • Issue: Selected values don’t persist after page reload.
    • Fix: Initialize the array property in mount():
      public $selected_skills = [];
      

Debugging

  1. Console Logs:

    • Use Alpine.js $wire events to debug interactions:
      x-data="{
          init() {
              this.$wire.on('model.changed', (value) => {
                  console.log('Selected value:', value);
              });
          }
      }"
      
    • Check the browser’s Network tab for Livewire wire:model updates.
  2. Livewire Wire:model:

    • If the dropdown updates but the Livewire property doesn’t, inspect the $wire object in the browser console:
      console.log(this.$wire.get('country_id'));
      

Tips

  1. Performance:

    • Large Datasets: Use ->take(100) or pagination to limit initial load.
    • Debounce Search: The component includes client-side debouncing by default (no extra config needed).
  2. Dark Mode:

    • Automatically adapts to your Tailwind dark mode setup. Test with:
      <x-searchable-select dark />
      
  3. Custom Styling:

    • Override the default Blade view by publishing assets:
      php artisan vendor:publish --tag=searchable-select-views
      
    • Modify the published resources/views/components/searchable-select.blade.php.
  4. Accessibility:

    • The component includes ARIA attributes by default. For custom labels, use:
      <x-searchable-select
          aria-label="Select a country"
      />
      
  5. Clearable Behavior:

    • Disable the clear button with :clearable="false" if needed:
      <x-searchable-select
          :clearable="false"
      />
      
  6. Validation Integration:

    • Combine with Livewire validation for seamless UX:
      public function rules() {
          return ['country_id' => 'required|exists:countries,id'];
      }
      
      @error('country_id')
          <span class="text-red-500">{{ $message }}</span>
      @enderror
      
  7. Testing:

    • Test interactions with Livewire’s assertSet() and assertInput():
      public function test_dropdown_selection() {
          $this->set('country_id', 1);
          $this->assertSet('country_id', 1);
      }
      
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.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme
agtp/agtp-php
agtp/mod-php
centraldesktop/protobuf-php