Multi-select form component for Phoenix LiveView.
multi_select/1 renders a native <select multiple> element with PhiaUI
styling, selected-value chip display, and remove-chip buttons. It is suited
for selecting predefined options from a fixed list (unlike tags_input/1
which accepts freeform text typed by the user).
form_multi_select/1 wraps the bare component with Phoenix.HTML.FormField
integration: label, error messages, and automatic id/name/value extraction.
When to use
- The user picks one or more values from a known, finite list of options.
- You want zero JavaScript with native browser multi-select semantics.
- An accessible chip row showing current selections is required.
For freeform tag entry, use phia_tags_input/1 instead.
Basic usage
<.multi_select
id="framework-select"
name="frameworks"
options={[{"Elixir", "elixir"}, {"Phoenix", "phoenix"}, {"LiveView", "liveview"}]}
selected={@selected_frameworks}
placeholder="Select frameworks..."
on_change="update_frameworks"
/>Form integration
<.form_multi_select
field={@form[:categories]}
options={@category_options}
label="Categories"
on_change="update_categories"
/>Handling events
The chip remove buttons emit phx-click={@on_change} with
phx-value-deselect={val}, so the LiveView can pattern-match:
def handle_event("update_frameworks", %{"deselect" => val}, socket) do
updated = List.delete(socket.assigns.selected_frameworks, val)
{:noreply, assign(socket, selected_frameworks: updated)}
endThe native <select multiple> submission sends all selected values as
name[] parameters to the server automatically via form submit.
Accessibility
<select multiple>usesaria-label={@placeholder}for screen readers.- Chip remove buttons carry
aria-label="Remove {value}". - The
disabledattribute is forwarded to the<select>element.
Summary
Functions
Phoenix.HTML.FormField-integrated multi-select with label and error display.
Renders a native <select multiple> with chip display for selected values.
Functions
Phoenix.HTML.FormField-integrated multi-select with label and error display.
Extracts id, name, and value from the field struct and delegates to
multi_select/1. Renders changeset errors below the select in
text-destructive colour.
Example
<.form_multi_select
field={@form[:categories]}
options={@category_options}
label="Categories"
on_change="update_categories"
/>Attributes
field(Phoenix.HTML.FormField) (required) - APhoenix.HTML.FormFieldstruct from@form[:field_name]. Provides the elementid,name, currentvalue(used as selected list), anderrorsfor changeset error display.label(:string) - Text rendered in a<label>above the select. Omitted whennil. Defaults tonil.options(:list) - List of{label, value}tuples — forwarded tomulti_select/1. Defaults to[].on_change(:string) - LiveView event name for chip removal — forwarded tomulti_select/1. Defaults tonil.class(:string) - Additional Tailwind CSS classes merged into the root<div>wrapper. Defaults tonil.disabled(:boolean) - Forwarded to the underlyingmulti_select/1to disable the select. Defaults tofalse.
Renders a native <select multiple> with chip display for selected values.
Selected values appear as removable chips above the native select. Each chip
shows the human-readable label (resolved via find_label/2) and a × button
that fires the on_change event with phx-value-deselect.
The native <select multiple> follows below and marks the matching options
as selected. This dual representation lets the component work both with
standard form submission and LiveView event-driven updates.
Examples
<%!-- Basic usage --%>
<.multi_select
id="roles"
name="roles"
options={[{"Admin", "admin"}, {"Member", "member"}, {"Viewer", "viewer"}]}
selected={@roles}
placeholder="Assign roles..."
on_change="update_roles"
/>
<%!-- Disabled --%>
<.multi_select
id="locked"
name="locked"
options={[{"A", "a"}, {"B", "b"}]}
selected={["a"]}
disabled={true}
on_change="noop"
/>Attributes
id(:string) (required) - HTMLidattribute for the underlying<select>element.name(:string) (required) - Basenameattribute. The component automatically appends[]to producename[], so all selected values are submitted as an array.options(:list) - List of{label, value}tuples to render as<option>elements.labelis the human-readable text;valueis the submitted form value.Defaults to
[].selected(:list) - List of currently selected values (strings). Options whose value appears in this list are rendered with theselectedattribute and displayed as removable chips above the select.Defaults to
[].placeholder(:string) - Placeholder text used as thearia-labelof the<select>element. Helps screen-reader users understand what to select.Defaults to
"Select...".on_change(:string) - LiveView event name fired when the user clicks a chip's remove button. The event receivesphx-value-deselectwith the value being removed.Defaults to
nil.class(:string) - Additional Tailwind CSS classes merged into the root<div>wrapper viacn/1. Defaults tonil.disabled(:boolean) - Whentrue, the<select>element is rendered with thedisabledattribute. Defaults tofalse.