Wirestrap is still in active development
This project is pre-1.0 and may introduce breaking changes at any time without prior notice.
Select
Custom select dropdown with single and multiple selection and optional search.
Options are provided either as a PHP array via options, or through a
Livewire method via wire-options. Pass options for fixed
or PHP-generated lists. When the list is large, expensive to produce, or depends on
database state, wire-options is a better fit: the method is called once
on first open and the result is cached client-side. If a value is already bound on
load, the method is called immediately to resolve the display label.
Because selection changes are applied via $wire.$set() internally,
wire:model.live has no effect: use the live prop instead.
Keyboard:
- ↑ ↓ to navigate.
-
Enter to select when the dropdown is open.
When closed, Enter submits the parent form if there is one, or opens the dropdown otherwise. - Escape to close.
Basic usage
Declare a method on your Livewire component and pass its name to
wire-options. Use icon to add an icon,
and floating for a floating label layout.
#[Renderless]
public function getLanguages(): array
{
return [
['value' => 'en', 'label' => 'English'],
['value' => 'fr', 'label' => 'French'],
];
}
{{-- Standard --}}
<x-wirestrap::select
id="language-select"
label="Language"
wire:model="language"
wire-options="getLanguages"
icon="bi-translate"
/>
{{-- Floating label --}}
<x-wirestrap::select ... floating />
Icon prop
The icon prop accepts any class string from your preferred icon library,
or an array of attributes for full control. Custom icon components are also supported,
see icon configuration.
Multiple
Add multiple to enable multi-selection.
wire:model must bind to an array property.
Selected options appear as badges with remove buttons, sorted
alphabetically.
public array $selectedLanguages = [];
<x-wirestrap::select ... multiple />
Search
Add search to show a text input at the top of the dropdown.
Options are filtered as you type. When the dropdown opens, focus moves to
the search input automatically.
<x-wirestrap::select ... search />
Reactive list
Use wire-options-watch to invalidate the options cache when a
Livewire property changes. The list reloads immediately if the dropdown is open or has a selected value,
so the label can be resolved. Otherwise, it will reload the next time the dropdown is opened.
To force a reload imperatively, use $wirestrap.select.refresh(id).
<x-wirestrap::select
...
wire:model="category"
wire-options="getCategories"
/>
<x-wirestrap::select
...
wire:model="categoryItem"
wire-options="getCategoryItems"
wire-options-watch="category"
/>
Option groups
Add an optgroup field to options that should be grouped.
Options sharing the same value are rendered together under that label.
Options without optgroup appear after all groups.
#[Renderless]
public function getCountries(): array
{
return [
['value' => 'fr', 'label' => 'France', 'optgroup' => 'Europe'],
['value' => 'de', 'label' => 'Germany', 'optgroup' => 'Europe'],
['value' => 'us', 'label' => 'United States', 'optgroup' => 'Americas'],
// No optgroup: appears after all groups
['value' => 'xx', 'label' => 'Other'],
];
}
Empty value
When the bound value equals empty-value, the component
displays the placeholder instead of a selection. Useful for filters where
a specific value like "0" or "all" means
"no filter applied".
<x-wirestrap::select ... empty-value="0" />
Disabled
Use disabled to disable the whole component. Individual options
can be disabled by setting 'disabled' => true on their array entry.
<x-wirestrap::select ... disabled />
// Set disabled on individual entries in the returned array
[
'value' => 'de',
'label' => 'German',
'disabled' => true,
],
Rich content
Use html_prefix and html_suffix on individual option entries
to inject raw HTML before and after the label. The label itself is always rendered as
plain text. Use class on an option to apply a CSS class to its element.
// Pass free HTML before and / or after the label
[
'value' => $user->id,
'html_prefix' => '<i class="bi bi-person"></i>',
'label' => $user->name,
'html_suffix' => '<span class="badge-' . $user->role->color . '">' . $user->role->name . '</span>',
],
Inline options
Pass options directly as a PHP array with options instead of a Livewire method.
The short form accepts an associative array of value => label pairs.
The full form supports the same fields as a wire-options method would return:
disabled, optgroup, class, html_prefix, html_suffix.
Options update automatically when Livewire re-renders the component.
{{-- Short syntax --}}
<x-wirestrap::select
...
:options="[
'fr' => 'France',
'de' => 'Germany',
'es' => 'Spain'
]"
/>
{{-- Full form with html_prefix / html_suffix --}}
<x-wirestrap::select
...
:options="[
['value' => 1, 'label' => 'Alice Martin', ...],
['value' => 2, 'label' => 'Bob Dupont', ...],
]"
search
/>
Validation
The component checks $errors for the wire:model
key and applies the invalid state if found. Try submitting without selecting
a language.
{{-- Suppress both the invalid class and the error message --}}
<x-wirestrap::select ... :has-validation="false" />
{{-- Keep the invalid class, hide the error message --}}
<x-wirestrap::select ... :has-validation-message="false" />
Props
Global configuration
Most prop defaults can be overridden globally via config/wirestrap.php.
x-wirestrap::select
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string|null |
null |
Unique identifier. Required (strict mode is on by default). |
label |
ComponentSlot|string|null |
null |
Label text or slot content. No label element is rendered when null. |
icon |
string|array |
null |
Icon identifier forwarded to the configured icon component. Always placed at start. |
options |
array|null |
null |
Options as a PHP array. Short form: ['value' => 'Label']. Full form: array of option definitions — see Option definition below. Updates automatically on Livewire re-render. Mutually exclusive with wire-options. |
wire-options |
string|null |
null |
Livewire method name returning the options array — see Option definition below. Called once on first open and cached client-side. Called immediately on load if a value is already bound. |
wire-options-watch |
string|null |
null |
Livewire property to watch. Invalidates the cache on change; reloads immediately if the dropdown is open. Requires wire-options. |
placeholder |
string |
config |
Text shown when no option is selected. |
search-placeholder |
string |
config |
Placeholder text for the search input. |
floating |
bool |
false |
Use floating label layout. |
disabled |
bool |
false |
Disable the component. |
multiple |
bool |
config |
Enable multiple selection. wire:model must bind to an array property. |
search |
bool |
config |
Show a search input inside the dropdown. Filtering is client-side. |
live |
bool |
config |
Trigger a server round-trip on each selection change instead of deferring. |
has-validation-message |
bool |
config |
Render the error message below the field. |
has-validation |
bool |
config |
Apply the invalid class when the wire:model key has an error. |
empty-value |
mixed |
config |
Value treated as empty: shows the placeholder and removes the selected state. |
default-attributes |
array |
config |
Default HTML attributes merged onto the root element. |
dropdown-offset |
int |
config |
Y-axis offset in pixels between the trigger and the dropdown. |
|
No results found
|
|||
Option definition
| Prop | Type | Default | Description |
|---|---|---|---|
value |
mixed |
-- |
The value bound to wire:model on selection. |
label |
string |
'' |
Display text. Always rendered as plain text. |
disabled |
bool |
false |
Disables the option. |
optgroup |
string |
null |
Group label. Options sharing the same value are rendered together. Options without optgroup appear after all groups. |
class |
string |
null |
Extra CSS class applied to the option element. |
html_prefix |
string |
null |
Raw HTML injected before the label. |
html_suffix |
string |
null |
Raw HTML injected after the label. |
|
No results found
|
|||
$wirestrap.select
| Method | Type | Default | Description |
|---|---|---|---|
$wirestrap.select.refresh(id) |
-- |
-- |
Discard the cached options and call wire-options immediately. id is the component's id attribute. |
|
No results found
|
|||