Choices

This component is intended to be used to build complex selection interfaces for single and multiple values. It also supports search on frontend or server, when dealing with large lists.

Most of time you just need a simple Select component, which renders nice natively on every device.

Selection

By default, it will look up for:

  • $object->id for option value.
  • $object->name for option display label.
  • $object->avatar for avatar picture.

 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

 
No results found.
adrienne88
Lake Cierraberg

rylee34
South Aylin

tamara42
Port Americobury

block.linda
Mohammadport

bailee.beier
Olsonstad

uterry
Kshlerinchester

kendra31
Port Jana

swaniawski.helene
South Dorthaborough

It has custom options
@php
$users = $this->users;
@endphp
{{-- Notice `single` --}}
<x-choices label="Single" wire:model="user_id" :options="$users" single />
 
{{-- public array $users_multi_ids = []; --}}
<x-choices label="Multiple" wire:model="users_multi_ids" :options="$users" />
 
{{-- Custom options --}}
<x-choices
label="Custom options"
wire:model="user_custom_id"
:options="$users"
option-label="username"
option-sub-label="city.name"
option-avatar="other_avatar"
icon="o-users"
height="max-h-96" {{-- Default is `max-h-64` --}}
hint="It has custom options"
single />

Select All

This option only works for multiple and non-searchable exclusively.


 
Select all
Remove all
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

 
Select all stuff
Delete all things
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

@php
$users = $this->users;
@endphp
{{-- Notice `allow-all` --}}
<x-choices label="Multiple" wire:model="users_all_ids" :options="$users" allow-all />
 
<x-choices
label="Multiple"
wire:model="users_all2_ids"
:options="$users"
allow-all
allow-all-text="Select all stuff"
remove-all-text="Delete all things" />

Compact mode

This option only works for multiple and non-searchable exclusively.


selected
 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

stuff chosen
 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

@php
$users = $this->users;
@endphp
{{-- Notice `compact` --}}
<x-choices label="Compact" wire:model="users_compact_ids" :options="$users" compact />
 
<x-choices
label="Compact label"
wire:model="users_compact2_ids"
:options="$users"
compact
compact-text="stuff chosen" />

You can combine allow-all and compact

selected
 
Select all
Remove all
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

@php
$users = $this->users;
@endphp
<x-choices
label="Select All + Compact"
wire:model="users_all_compact_ids"
:options="$users"
compact
allow-all />

Searchable (frontend)

If you judge you don't have a huge list of items, you can make it searchable offline on "frontend side". But, if you have a huge list it is a better idea to make it searchable on "server side", otherwise you can face some slow down on frontend. See on next section.


 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

@php
$users = $this->users;
@endphp
{{-- Notice `searchable` --}}
{{-- Notice this is a different component, but with same API --}}
<x-choices-offline
label="Single (frontend)"
wire:model="user_searchable_offline_id"
:options="$users"
single
searchable />
 
<x-choices-offline
label="Multiple (frontend)"
wire:model="users_multi_searchable_offline_ids"
:options="$users"
searchable />

Searchable (server)

When dealing with large options list use searchable parameter. By default, it calls search() method to get fresh options from "server side" while typing. You can change the method's name by using search-function parameter.


 
No results found.
Adam

Adele

Adolphus

Alanna

Albin

 
Ops! Nothing here ...
Adam

Adele

Adolphus

Alanna

Albin

@php
$usersSearchable = $this->usersSearchable;
$usersMultiSearchable = $this->usersMultiSearchable;
@endphp
{{-- Notice `searchable` + `single` --}}
<x-choices
label="Searchable + Single"
wire:model="user_searchable_id"
:options="$usersSearchable"
single
searchable />
 
{{-- Notice custom `search-function` --}}
<x-choices
label="Searchable + Multiple"
wire:model="users_multi_searchable_ids"
:options="$usersMultiSearchable"
search-function="searchMulti"
no-result-text="Ops! Nothing here ..."
searchable />

You must also consider displaying pre-selected items on list, when it first renders and while searching. There are many approaches to make it work, but here is an example for single search using Volt.

new class extends Component {
 
// Selected option
public ?int $user_searchable_id = null;
 
// Options list
public Collection $usersSearchable;
 
public function mount()
{
// Fill options when component first renders
$this->search();
}
 
// Also called as you type
public function search(string $value = '')
{
// Besides the search results, you must include on demand selected option
$selectedOption = User::where('id', $this->user_searchable_id)->get();
 
$this->usersSearchable = User::query()
->where('name', 'like', "%$value%")
->take(5)
->orderBy('name')
->get()
->merge($selectedOption); // <-- Adds selected option
}
}

Sometimes you don't want to hit a datasource on every keystroke. So, you can make use of debounce to control over how often a network request is sent.

Another approach is to use min-chars attribute to avoid hit search method itself until you have typed such amount of chars.

 
No results found.
@php
$usersSearchableMinChars = $this->usersSearchableMinChars;
@endphp
{{-- Notice `min-chars` and `debounce` --}}
<x-choices
label="Searchable + Single + Debounce + Min chars"
wire:model="user_searchable_min_chars_id"
:options="$usersSearchableMinChars"
search-function="searchMinChars"
debounce="300ms" {{-- Default is `250ms`--}}
min-chars="2" {{-- Default is `0`--}}
single
searchable />

You can pass any extra arbitrary search parameters like this.

{{-- Notice `search-function` with extra arbitrary parameters --}}
<x-choices
label="Extra parameters"
wire:model="user_id"
:options="$users"
search-function="searchExtra(123, 'thing')"
searchable />
public function search(string $value = '', int $extra1 = 0, string $extra2 = '')
{
// The first parameter is the default and comes from the search input.
}

Slots

You have full control on rendering items by using the @scope('item', $object) special blade directive. It injects the current $object from the loop's context and achieves the same behavior that you would expect from the Vue/React scoped slots.

You can customize the list item and selected item slot. Searchable (online) works with blade syntax.

 
No results found.
Eudora
Et odio odio est neque ut tempora ea rerum. Id suscipit repudiandae culpa dolorem. Inventore sapiente dicta incidunt eaque illo.
adrienne88

Luther
Aperiam voluptatem porro corporis non fuga hic tempore. Sint aut inventore autem molestias consectetur libero voluptas. Illo dolor ipsa sed eum similique repellendus ipsam. Non voluptas et laboriosam temporibus eligendi.
rylee34

Donavon
Aspernatur quaerat et aspernatur molestiae. Dolor placeat praesentium aut suscipit delectus eos explicabo. Ut sit animi distinctio vero. Ut dolorum labore quod voluptatem rerum.
tamara42

Magdalena
Sit aut consequatur voluptas ut voluptatem dolor iste. Nulla maiores vel facere reprehenderit. Eum aliquid blanditiis esse qui deserunt.
block.linda

Rigoberto
Ut ut et vel quam at dolor voluptate. Non ut est repellendus sed consectetur et amet. Magnam dicta laudantium doloremque sit. Iusto earum magni est veritatis perspiciatis dolore dolorem. Eligendi voluptatem quis dolor veniam beatae consequatur.
bailee.beier

Noelia
Recusandae sint voluptates quod delectus excepturi. Quia in corporis quam qui autem natus. Totam quia rerum qui recusandae deleniti. Harum repellendus vitae iste voluptatem aut. Incidunt est voluptas nesciunt consectetur.
uterry

Jaida
Harum earum molestiae similique provident nemo. Magnam provident aut ullam doloribus laboriosam veniam laboriosam. Sed quod reiciendis et doloremque itaque.
kendra31

Derrick
Repellat quia nulla accusamus vel quas iure expedita. Sequi et dolorem aut nam aut expedita. Iste veritatis fugit voluptas blanditiis quibusdam. Voluptas exercitationem asperiores veniam quam.
swaniawski.helene

<div>
@php $users = $this->users; @endphp
</div>
<x-choices label="Slots (online)" wire:model="user_custom_slot_id" :options="$users" single>
{{-- Item slot--}}
@scope('item', $user)
<x-list-item :item="$user" sub-value="bio">
<x-slot:avatar>
<x-icon name="o-user" class="bg-orange-100 p-2 w-8 h8 rounded-full" />
</x-slot:avatar>
<x-slot:actions>
<x-badge :value="$user->username" />
</x-slot:actions>
</x-list-item>
@endscope
 
{{-- Selection slot--}}
@scope('selection', $user)
{{ $user->name }} ({{ $user->username }})
@endscope
</x-choices>

You can append or prepend anything like this. Make sure to use appropriated css round class on left or right.

 
No results found.
Eudora

Luther

Donavon

Magdalena

Rigoberto

Noelia

Jaida

Derrick

<div>
@php $users = $this->users @endphp
</div>
<x-choices label="Slots" wire:model="user_custom_slot_id" :options="$users" single>
<x-slot:prepend>
{{-- Add `rounded-e-none` (RTL support) --}}
<x-button icon="o-trash" class="rounded-e-none" />
</x-slot:prepend>
<x-slot:append>
{{-- Add `rounded-e-none` (RTL support) --}}
<x-button label="Create" icon="o-plus" class="rounded-s-none btn-primary" />
</x-slot:append>
</x-choices>

Events

You can catch component events just like described on Livewire docs. In this case the component will trigger the @change-selection and it will contain the selected items keys.

The payload contains a single key or an array of keys, depending on how you set the component. Because it is a custom event, you must access the key(s) via the detail.value property on the event.

<x-choices ... @change-selection="console.log($event.detail.value)" />
<x-choices-offline ... @change-selection="console.log($event.detail.value)" />

maryUI
Sponsor