Select several related values from a hierarchy. Branch checkboxes select their enabled descendant leaves, while the bound value stays a simple array of leaf values.
<flux:tree-select wire:model="categoryIds" searchable> <flux:tree-select.item label="Engineering" expanded> <flux:tree-select.item label="Frontend"> <flux:tree-select.item value="livewire" label="Livewire" /> <flux:tree-select.item value="alpine" label="Alpine.js" /> <flux:tree-select.item value="flux" label="Flux UI" /> </flux:tree-select.item> <flux:tree-select.item label="Backend"> <flux:tree-select.item value="laravel" label="Laravel" /> </flux:tree-select.item> </flux:tree-select.item></flux:tree-select>
Tree select's JavaScript is fetched automatically the first time the component is rendered. It is kept out of Flux's main JavaScript bundle, so pages without a tree select do not pay its runtime cost.
public array $categoryIds = ['livewire', 'alpine'];
protected function rules(): array{ return [ 'categoryIds' => ['array'], 'categoryIds.*' => ['string', 'distinct', Rule::exists('categories', 'id')], ];}
Selecting a branch selects all enabled descendant leaves. Clearing one descendant puts every ancestor on its path into a mixed state. Disabled descendants are excluded from branch selection and totals.
<flux:tree-select wire:model="teamIds"> <flux:tree-select.item label="Product"> <flux:tree-select.item value="design" label="Design" /> <flux:tree-select.item value="engineering" label="Engineering" /> <flux:tree-select.item value="research" label="Research" disabled /> </flux:tree-select.item></flux:tree-select>
Add searchable to filter the fully rendered tree on the client. Matching leaves keep their ancestor path, and keywords provide aliases without changing the visible label.
<flux:tree-select searchable search:placeholder="Search locations..."> <flux:tree-select.item label="United States"> <flux:tree-select.item value="ny" label="New York" keywords="NY NYC Empire State" /> </flux:tree-select.item></flux:tree-select>
Search is local and hierarchy-preserving. Render the complete tree before searching; remote search and lazy-loaded children are not supported because a partial branch cannot reliably calculate cascade or mixed state.
Generate the hierarchy with Blade loops or recursive partials. Livewire may insert, remove, rename, and reorder items; use stable wire:key values so expansion and selection reconcile cleanly. Selected values remain in the model while their leaves are temporarily absent and become selected again if those leaves return.
["laravel"]
<flux:tree-select wire:model="categoryIds" searchable> @foreach ($categories as $category) @include('categories.tree-select-item', ['category' => $category]) @endforeach</flux:tree-select><!-- categories/tree-select-item.blade.php -->@if ($category->children->isEmpty()) <flux:tree-select.item :value="(string) $category->id" :label="$category->name" :disabled="$category->disabled" :wire:key="'tree-category-'.$category->id" />@else <flux:tree-select.item :label="$category->name" :disabled="$category->disabled" :wire:key="'tree-category-'.$category->id" > @foreach ($category->children as $child) @include('categories.tree-select-item', ['category' => $child]) @endforeach </flux:tree-select.item>@endif
Tree select matches Flux form controls in default, small, and extra-small sizes, and integrates with fields, validation, and disabled state.
<flux:tree-select /><flux:tree-select size="sm" /><flux:tree-select size="xs" /><flux:tree-select invalid /><flux:tree-select disabled />
| Key | Open tree behavior |
|---|---|
| Arrow Down / Arrow Up | Move through visible tree items |
| Arrow Right | Expand a branch, then move to its first child |
| Arrow Left | Collapse a branch, then move to its parent |
| Home / End | Move to the first or last visible item |
| Enter | Toggle the active item's checkbox |
| Space | Toggle the active item when focus is on the trigger; enter a space when focus is in search |
| Escape | Close and restore focus to the trigger |
| Tab | Close and continue normal page tab order |
|
Prop
|
Description
|
|---|---|
| wire:model |
Livewire property containing an array of selected leaf values.
|
| value |
Initial array of selected leaf values.
|
| name |
Form field name used to generate hidden array inputs.
|
| placeholder |
Text shown when no leaves are selected.
|
| size |
Size of the trigger control.
|
| searchable |
Show local hierarchy-preserving search.
|
| search:placeholder |
Placeholder and accessible label for the search field.
|
| selected-suffix |
Text displayed after the selected count when two or more leaves are selected. A single selection displays its item label.
|
| clearable |
Show an inline clear button in the trigger when the selection is non-empty.
|
| position |
Preferred popover position relative to the trigger.
|
| align |
Popover alignment relative to the trigger.
|
| label |
Field label displayed above the control.
|
| description |
Field help text displayed below the control.
|
| disabled |
Disable the complete control.
|
| invalid |
Display the invalid control state.
|
|
Prop
|
Description
|
|---|---|
| value |
Required leaf value. Omit it from branches.
|
| label |
Required visible, searchable, and accessible label.
|
| keywords |
Optional search aliases as a string or array.
|
| expanded |
Initially expand a branch.
|
| description |
Secondary text displayed under the label.
|
| icon |
Flux icon rendered before the item label and retained in the trigger when that leaf is the only selection.
|
| disabled |
Prevent selection. Disabled leaves are excluded from branch cascade.
|