Features
Livewire Async Select comes packed with features to handle any select use case.
🚀 Asynchronous Loading
Load options dynamically from API endpoints with built-in search and filtering.
<livewire:async-select
endpoint="/api/users/search"
wire:model="userId"
placeholder="Search users..."
/>
Features:
- Automatic debouncing
- Minimum search length configuration
- Loading states
- Error handling
🔍 Search & Filter
Real-time search through local or remote options.
<livewire:async-select
:options="$largeDataset"
:min-search-length="2"
placeholder="Type to search..."
/>
Features:
- Client-side filtering for local options
- Server-side search for remote data
- Configurable minimum length
- Debounced input
- Disable search with
:searchable="false"for small option lists
🎯 Multiple Selection
Select multiple items with beautiful chip/tag display.
<livewire:async-select
wire:model="selectedItems"
:options="$options"
:multiple="true"
placeholder="Select multiple..."
/>
Features:
- Visual chips for selected items
- Easy removal of individual selections
- Maximum selection limits
- Bulk selection support
🏷️ Tags Mode
Create custom tags on-the-fly.
<livewire:async-select
wire:model="tags"
:multiple="true"
:tags="true"
placeholder="Create tags..."
/>
Features:
- Create custom options
- Prevent duplicates
- Custom validation
- Mix predefined and custom options
🎨 Custom Rendering
Fully customize how options and selected items appear.
<livewire:async-select :options="$users">
<x-slot name="slot" :option="$option">
<div class="flex items-center gap-2">
<img src="{{ $option['avatar'] }}" class="w-8 h-8 rounded-full">
<div>
<div class="font-bold">{{ $option['label'] }}</div>
<div class="text-sm text-gray-500">{{ $option['email'] }}</div>
</div>
</div>
</x-slot>
</livewire:async-select>
🎭 Theme Support
Built-in support for Tailwind CSS and Bootstrap.
<!-- Tailwind (default, or uses config) -->
<livewire:async-select ui="tailwind" />
<!-- Bootstrap -->
<livewire:async-select ui="bootstrap" />
<!-- Uses config default -->
<livewire:async-select :options="$options" />
You can configure the default theme globally in config/async-select.php:
'ui' => env('ASYNC_SELECT_UI', 'tailwind'),
📸 Image Support
Display images or avatars alongside option labels.
<livewire:async-select
:options="[
['value' => 1, 'label' => 'John', 'image' => '/avatars/john.jpg'],
['value' => 2, 'label' => 'Jane', 'image' => '/avatars/jane.jpg']
]"
/>
👥 Grouped Options
Organize options into labeled groups.
<livewire:async-select
:options="[
['value' => 'apple', 'label' => 'Apple', 'group' => 'Fruits'],
['value' => 'carrot', 'label' => 'Carrot', 'group' => 'Vegetables']
]"
/>
🚫 Disabled Options
Mark specific options as non-selectable.
<livewire:async-select
:options="[
['value' => '1', 'label' => 'Available'],
['value' => '2', 'label' => 'Sold Out', 'disabled' => true]
]"
/>
🗑️ Clearable
Allow users to clear their selection.
<livewire:async-select
wire:model="selection"
:clearable="true"
/>
➕ Suffix Button
Add a customizable button on the right side of the select input. Perfect for adding new items, opening modals, or triggering custom actions.
<livewire:async-select
wire:model="selectedMedia"
:options="$media"
:suffix-button="true"
suffix-button-action="showAddMediaModal"
placeholder="Select Media..."
/>
Features:
- Customizable icon (defaults to plus icon)
- Dispatches Livewire events on click
- Styled to match the select input
- RTL support
- Automatically closes dropdown when clicked (v1.1.0) - Perfect for opening modals
Version 1.1.0 Enhancement
When the suffix button is clicked, the dropdown automatically closes. This ensures a clean user experience when opening modals, especially when using custom slots. The dropdown closure happens before the event is dispatched, preventing any UI conflicts.
With Custom Icon:
<livewire:async-select
wire:model="selectedMedia"
:options="$media"
:suffix-button="true"
suffix-button-action="showTest"
suffix-button-icon="<svg>...</svg>"
/>
Opening Modals (v1.1.0):
Perfect for opening modals to add or select items. The dropdown closes automatically:
<livewire:async-select
wire:model="selectedMedia"
:options="$media"
:suffix-button="true"
suffix-button-action="showAddMediaModal"
placeholder="Select Media..."
>
<x-slot name="selectedSlot" :option="$option">
<div class="flex items-center gap-2">
<img src="{{ $option['image'] }}" class="w-6 h-6 rounded">
<span>{{ $option['label'] }}</span>
</div>
</x-slot>
</livewire:async-select>
#[On('showAddMediaModal')]
public function showAddMediaModal()
{
// Dropdown is already closed when this method is called
$this->showModal = true;
}
Listening to Events:
#[On('suffix-button-clicked')]
public function handleSuffixButton()
{
// Handle button click
// Dropdown is automatically closed
$this->showModal = true;
}
Or with a custom action name:
<livewire:async-select
suffix-button-action="showAddMediaModal"
/>
#[On('showAddMediaModal')]
public function showAddMediaModal()
{
$this->showModal = true;
}
⌨️ Keyboard Navigation
Full keyboard support for accessibility:
- Arrow Up/Down: Navigate options
- Enter: Select highlighted option
- Escape: Close dropdown
- Backspace: Remove last selection (multiple mode)
- Tab: Navigate away
🔗 Two-way Binding
Native Livewire wire:model support:
<livewire:async-select wire:model.live="value" />
Supports all wire:model modifiers:
wire:model.livewire:model.blurwire:model.defer
📦 Collection Support
Automatically converts Laravel Collections to arrays:
// No need to call ->toArray() or ->all()
$users = User::all()->map(fn($user) => [
'value' => $user->id,
'label' => $user->name
]);
// Pass directly to component
return view('form', ['users' => $users]);
<livewire:async-select :options="$users" />
Works with:
- Eloquent Collections
- Support Collections
- Database Collections
- Lazy Collections
🎯 Extra Parameters
Pass additional parameters to API endpoints:
<livewire:async-select
endpoint="/api/cities"
:extra-params="['country_id' => $countryId, 'active' => true]"
/>
🔐 Authentication
Custom Headers
Pass custom headers (e.g., for authentication) with HTTP requests:
<livewire:async-select
endpoint="/api/users/search"
wire:model="userId"
:headers="[
'Authorization' => 'Bearer ' . $token,
'X-Custom-Header' => 'custom-value'
]"
/>
Internal Authentication
Automatically authenticate requests to same-domain endpoints:
<livewire:async-select
endpoint="/api/users/search"
wire:model="userId"
:use-internal-auth="true"
/>
Features:
- Automatic token generation for authenticated users
- Signed tokens with request binding
- Replay attack protection
- Key rotation support
- Works seamlessly with Laravel middleware
📱 Responsive
Works perfectly on all screen sizes:
- Desktop
- Tablet
- Mobile devices
♿ Accessible
Built with accessibility in mind:
- ARIA attributes
- Keyboard navigation
- Screen reader support
- Focus management
🔄 Loading States
Visual feedback during async operations:
- Spinner during search
- Loading indicator
- Disabled state while fetching
✅ Validation
Full Laravel validation support:
$this->validate([
'selectedUser' => 'required|exists:users,id'
]);
🎨 Customizable
- Publishable views
- Configurable options
- Custom styling
- Slot-based rendering
Performance Features
- Debouncing: Reduces API calls
- Lazy Loading: Load options on demand
- Caching: Optional result caching
- Minimal Bundle: Small JavaScript footprint