drpshtiwan/livewire-async-select
composer require drpshtiwan/livewire-async-select
php artisan vendor:publish --tag=async-select-assets
<head>
@asyncSelectStyles
@livewireStyles
</head>
<body>
{{ $slot }}
@livewireScripts
@stack('scripts') <!-- Required -->
</body>
<livewire:async-select
wire:model="userId"
endpoint="/api/users/search"
placeholder="Search users..."
/>
Backend Route:
Route::get('/api/users/search', function (Request $request) {
return User::where('name', 'like', "%{$request->search}%")
->limit(20)
->get(['id', 'name']);
})->middleware('auth:sanctum');
wire:model for automatic sync with Livewire properties.
<livewire:async-select wire:model="selectedUser" endpoint="/api/users" />
public $selectedUser = 1; // Auto-populates select
<livewire:async-select :options="$users" wire:model="userId" />
endpoint for async loading:
<livewire:async-select endpoint="/api/categories" wire:model="categoryId" />
multiple attribute:
<livewire:async-select
wire:model="selectedTags"
endpoint="/api/tags"
multiple
placeholder="Select tags..."
/>
selected-slot:
<livewire:async-select ...>
<livewire:slot name="selectedSlot">
<span class="bg-blue-100 text-blue-800 px-2 py-1 rounded">{{ $option['name'] }}</span>
</livewire:slot>
</livewire:async-select>
debounce attribute).value-labels to show selected items without API calls:
<livewire:async-select
wire:model="categoryId"
endpoint="/api/categories"
:value-labels="[3 => 'Web Dev', 5 => 'Design']"
/>
async-auth middleware:
Route::get('/api/secure-data', function () { ... })
->middleware('async-auth:sanctum');
X-Internal-User header for server-side auth.<livewire:async-select :options="$products">
<livewire:slot name="slot">
<div class="flex items-center">
<img src="{{ $option['thumbnail'] }}" width="30" class="mr-2">
<span>{{ $option['name'] }} (${{ $option['price'] }})</span>
</div>
</livewire:slot>
</livewire:async-select>
<livewire:slot name="selectedSlot">
<span class="badge badge-primary">{{ $option['name'] }}</span>
</livewire:slot>
<livewire:async-select
suffix-button
suffix-button-action="openModal"
placeholder="Select or add new..."
/>
// Alpine.js script
<script>
function openModal() {
@this.call('openAddItemModal');
}
</script>
Missing @stack('scripts'):
@stack('scripts') is in your layout’s <body>.API Response Format:
['data' => [...]].return response()->json(['data' => $items]);
Livewire 4 Slot Issues:
php artisan livewire:discover
Caching Headers:
Cache-Control: no-cache to API responses:
return response()->json(['data' => $items])
->header('Cache-Control', 'no-cache');
Multiple Selection Limits:
max-selections not enforced.<livewire:async-select ... max-selections="5" />
X-Internal-User header for auth.storage/logs/livewire.log for property sync errors.console.log(Alpine.store('asyncSelectStore'));
Tailwind vs. Bootstrap:
las-).@asyncSelectBootstrapV4Styles.las-* classes (e.g., .las-dropdown { z-index: 1000; }).Debounce Adjustments:
debounce="500" for slower networks).Empty State Handling:
empty-message:
<livewire:async-select ... empty-message="No users found" />
Custom Headers:
wire:model or Livewire property:
<livewire:async-select
wire:model="userId"
endpoint="/api/users"
:headers="['X-Custom-Header' => 'value']"
/>
Dynamic Endpoints:
<livewire:async-select
:endpoint="'/api/' . $resource . '/search'"
wire:model="selectedId"
/>
Server-Side Filtering:
wire:model filters:
// Livewire component
public $searchTerm = '';
public $selectedIds = [];
// API route
$query->where('name', 'like', "%{$request->searchTerm}%")
->whereNotIn('id', $request->selectedIds);
Accessibility:
aria-label and aria-controls are set for screen readers:
<livewire:async-select
aria-label="Search and select a user"
wire:model="userId"
endpoint="/api/users"
/>
lazy attribute to defer initial load:
<livewire:async-select lazy endpoint="/api/large-dataset" />
$items = User::where(...)
->paginate($request->per_page ?? 20);
return response()->json(['data' => $items]);
cache()->remember):
return cache()->remember("users_{$request->search}", now()->addMinutes(5), function () {
return User::where(...)->get();
});
api or web middleware with CSRF token.Route::middleware(['throttle:60,1'])->get('/api/search', ...);
How can I help you explore Laravel packages today?