uluumbch/alpine-select-livewire
composer require uluumbch/alpine-select-livewire
php artisan vendor:publish --provider="Uluumbch\AlpineSelectLivewire\AlpineSelectLivewireServiceProvider"
<livewire:alpine-select
wire:model="selectedOption"
:options="$options"
placeholder="Choose an option"
/>
public $selectedOption;
public $options = [
['id' => 1, 'name' => 'Option 1'],
['id' => 2, 'name' => 'Option 2'],
];
<livewire:alpine-select
wire:model="selectedOptions"
:options="$options"
placeholder="Select multiple..."
multiple
searchable
/>
public $selectedOptions = [];
public $options = collect([...]); // Large dataset (e.g., from DB)
wire:model for seamless reactivity.
<livewire:alpine-select
wire:model.defer="userRoles" <!-- Defer updates for performance -->
:options="$roles"
multiple
/>
mount() or updatedProperty():
public function mount() {
$this->options = Role::all()->pluck('name', 'id');
}
reorderable prop:
<livewire:alpine-select
wire:model="sortedTags"
:options="$tags"
multiple
reorderable
/>
public function updatedSortedTags($value) {
$this->tags = collect($value)->sortBy('order');
}
debounce directive:
<livewire:alpine-select
wire:model="searchResults"
:options="$allOptions"
searchable
@search.debounce.300ms="fetchOptions"
/>
public function fetchOptions($query) {
$this->options = Model::where('name', 'like', "%{$query}%")->get();
}
<livewire:alpine-select
:options="$users"
option-label="name"
option-value="id"
/>
<livewire:alpine-select>
<xslot name="option">
<div class="flex items-center">
<img src="{{ $option->avatar }}" width="20">
<span>{{ $option->name }}</span>
</div>
</xslot>
</livewire:alpine-select>
/* resources/css/app.css */
@layer components.alpine-select {
.alpine-select-dark .select__dropdown {
@apply bg-gray-800 text-white;
}
}
<div x-data="{ darkMode: true }">
<button @click="darkMode = !darkMode">Toggle Dark</button>
<livewire:alpine-select
:class="{ 'alpine-select-dark': darkMode }"
...
/>
</div>
Tailwind Processing:
vendor/uluumbch/alpine-select-livewire/resources/views is in tailwind.config.js content.npx tailwindcss -i input.css -o output.css --watch if using custom setup.Livewire Defer Conflicts:
wire:model.defer may cause lag with large datasets.wire:ignore on the component and manually sync:
<div wire:ignore>
<livewire:alpine-select @change="syncSelection" ... />
</div>
public function syncSelection($value) {
$this->selectedOptions = $value;
}
Option Format Mismatch:
option-label/option-value ignored if options aren’t objects/arrays.// Correct:
$options = collect([['id' => 1, 'name' => 'Foo']]);
// Or:
$options = Model::pluck('name', 'id');
Reorderable Multi-Select:
order keys:
public $selectedOptions = [
['id' => 1, 'name' => 'First', 'order' => 1],
['id' => 2, 'name' => 'Second', 'order' => 2],
];
x-data to debug:
<div x-data="{ select: {} }" x-init="select = $wire.model('selectedOptions')">
{{ $wire.entangle('selectedOptions') }}
</div>
public function boot() {
Livewire::configureToUseAlpineSelect();
Livewire::enableLogging(); // For debugging
}
Custom Events:
<livewire:alpine-select
@searching="console.log('Searching...')"
@selected="console.log('Selected:', $event.detail)"
/>
public function updatedSelectedOptions($value) {
$this->dispatch('select-changed', value: $value);
}
Slot Overrides:
<livewire:alpine-select>
<xslot name="no-options">
<p class="p-2 text-gray-500">No results found.</p>
</xslot>
</livewire:alpine-select>
Alpine Directives:
<livewire:alpine-select
x-init="
$watch('selectedOptions', (val) => {
console.log('Custom logic:', val);
})
"
/>
searchable + server-side filtering to avoid client-side overload.updated methods if adding custom logic:
public function updatedCustomField() {
$this->dispatch('alpine-init', script: '
$wire.off("change");
');
}
How can I help you explore Laravel packages today?