AutoComplete
Form auto-complete component.
Form Auto Complete, Customization Blocks
<!-- "items" accepts a plain array or a collection instance --> <x-autocomplete :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'], ['value' => 'Belo Horizonte'], ['value' => 'Curitiba'], ['value' => 'Porto Alegre'],]" />
<x-autocomplete label="City" hint="Start typing to filter the list" placeholder="Choose a city" :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'], ['value' => 'Belo Horizonte'], ]" />
<x-autocomplete label="Assignee" :items="[ ['value' => 'Taylor Otwell', 'description' => 'Creator of Laravel'], ['value' => 'Nuno Maduro', 'description' => 'Creator of PestPHP'], ['value' => 'Jess Archer', 'description' => 'Creator of Laravel Prompts'],]" />
<x-autocomplete label="Assignee" :items="[ [ 'value' => 'Taylor Otwell', 'description' => 'Creator of Laravel', 'image' => 'https://unavatar.io/github/taylorotwell', ], [ 'value' => 'Nuno Maduro', 'description' => 'Creator of PestPHP', 'image' => 'https://unavatar.io/github/nunomaduro', ], [ 'value' => 'Jess Archer', 'description' => 'Creator of Laravel Prompts', 'image' => 'https://unavatar.io/github/jessarcher', ],]" />
An option to pass special or additional values.
[ 'value' => 'Alice', 'description' => 'admin', 'metadata' => ['id' => 42, 'role' => 'admin', 'team_id' => 7], ]
<x-autocomplete wire:model="user" :request="route('api.users')" x-on:select="$wire.userPicked($event.detail.item.metadata)" />
Works identically for local items and remote results, since both go through the same normalization step.
An option to remap the item keys when they do not match the expected structure.
When the items — local or remote — name their fields differently, the select attribute remaps them instead of forcing a reshape at the source. Any part left out falls back to the key of the same name, and disabled is always read from disabled .
<!-- Format: value:key|description:key|image:key|metadata:key --> <x-autocomplete label="User" :items="$users" select="value:name|description:email|image:avatar" />
Optionally, you can set the mapping globally through the TallStackUI configuration file
An option for passing custom or additional values.
<x-autocomplete label="Status" :items="[ ['value' => 'Pending'], ['value' => 'Approved'], ['value' => 'Rejected', 'disabled' => true],]" />
<x-autocomplete label="City" clearable :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'], ['value' => 'Belo Horizonte'],]" />
<x-autocomplete label="IA" prefix="www" suffix=".com" :items="[ ['value' => 'claude'], ['value' => 'chatgpt'], ['value' => 'gemini.google'], ]" />
An option to set the minimum number of characters for the search.
<x-autocomplete label="City" lazy="2" :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'], ['value' => 'Belo Horizonte'], ['value' => 'Curitiba'], ['value' => 'Porto Alegre'], ['value' => 'Salvador'], ['value' => 'Recife'], ['value' => 'Fortaleza'],]" />
Without strict, wire:model accepts any typed value. With strict , the binding updates only after the user selects an item from the dropdown. If the current query does not match and the user leaves the field or presses Esc, the previous selection is restored. The field clears if there is no previous selection.
<x-autocomplete label="Status" strict :items="[ ['value' => 'Pending'], ['value' => 'Approved'], ['value' => 'Rejected'],]" />
Similar to the select.styled , the autocomplete can fetch items from a remote source:
<!-- Using a route as a string --><x-autocomplete label="User" request="/api/users" /> <!-- Using a Laravel route --><x-autocomplete label="User" :request="route('api.users')" />
The example below queries the same endpoint used by the styled select . It returns the user name under label , so select points the autocomplete value at it, while description and image already match:
<!--The endpoint below returns the user name under "label", so "select" pointsthe autocomplete "value" at it. "description" and "image" already match.--> <x-autocomplete label="User" placeholder="Type a user name..." :request="route('api.users')" select="value:label" clearable />
use App\Models\User;use Illuminate\Http\Request;use Illuminate\Support\Facades\Route; Route::get('/users', function (Request $request) { $search = $request->get('search'); return User::query() ->when($search, fn ($query) => $query->whereAny(['name', 'email'], 'like', "%{$search}%")) ->limit(10) ->get() ->map(fn (User $user): array => [ 'label' => $user->name, 'value' => $user->id, 'image' => $user->avatar, 'description' => $user->email, ]);})->name('api.users');
Like select.styled , this component accepts a request array for custom requests. Set url , choose get or post as the method , and add params . The component hydrates params before each request to keep Livewire properties current.
<x-autocomplete label="User" :request="[ 'url' => route('api.users'), 'method' => 'post', 'params' => ['team_id' => 7],]" />
Each item returned by the endpoint must match the :items structure. The value field is required, while description , image , and disabled are optional. Example:
use App\Models\User;use Illuminate\Http\Request;use Illuminate\Support\Facades\Route; Route::get('/users', function (Request $request) { $search = $request->input('search'); return User::query() ->when(! empty($search), fn ($query) => $query->where('name', 'like', "%{$search}%")) ->limit(10) ->get() ->map(fn (User $user): array => [ 'value' => $user->name, 'description' => $user->email, 'image' => $user->avatar, ]);})->name('api.users');
An option to swap the remote loading icon for a spinner.
<x-autocomplete label="User" placeholder="Type a user name..." :request="route('api.users')" select="value:label" indicator="spinner" /> <x-autocomplete label="User" placeholder="Type a user name..." :request="route('api.users')" select="value:label" indicator="spinner.bars" />
Type in the field to see the indicator. A bare spinner uses the globally configured spinner.type . spinner.{type} picks a specific spinner variant. Leaving it empty keeps the original icon. The inline attribute wins over the configuration file.
<x-autocomplete label="Readonly" value="São Paulo" readonly :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'],]" /><x-autocomplete label="Disabled" value="São Paulo" disabled :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'],]" />
<x-autocomplete label="User" request="/api/users" :placeholders="[ 'default' => 'Type a user name...', 'empty' => 'No user matches your search.', 'loading' => 'Searching users...', ]" />
An option for dealing with an empty search result and doing something with the searched value.
<x-autocomplete label="City" :items="[ ['value' => 'São Paulo'], ['value' => 'Rio de Janeiro'],]"> <x-slot:after> <div class="my-2 flex items-center justify-center px-2"> <x-button block x-on:click="$tsui.interaction('dialog').success('Done!', `Term: ${search}`).send()"> <span x-html="`Create city <b>${search}</b>`"></span> </x-button> </div> </x-slot:after></x-autocomplete>
<!--$event.detail.item: the picked row, including any extra keys you put on it.--> <x-autocomplete label="User" :items="[ ['value' => 'Alice', 'description' => 'admin'], ['value' => 'Bob', 'description' => 'editor'], ]" x-on:select="alert(`Selected: ${$event.detail.item.value}`)" x-on:clear="alert('Cleared')" x-on:open="console.log('opened')" x-on:close="console.log('closed')" />