PhiaUi.Components.MultiSelect (phia_ui v0.1.17)

Copy Markdown View Source

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)}
end

The native <select multiple> submission sends all selected values as name[] parameters to the server automatically via form submit.

Accessibility

  • <select multiple> uses aria-label={@placeholder} for screen readers.
  • Chip remove buttons carry aria-label="Remove {value}".
  • The disabled attribute 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

form_multi_select(assigns)

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) - A Phoenix.HTML.FormField struct from @form[:field_name]. Provides the element id, name, current value (used as selected list), and errors for changeset error display.

  • label (:string) - Text rendered in a <label> above the select. Omitted when nil. Defaults to nil.

  • options (:list) - List of {label, value} tuples — forwarded to multi_select/1. Defaults to [].

  • on_change (:string) - LiveView event name for chip removal — forwarded to multi_select/1. Defaults to nil.

  • class (:string) - Additional Tailwind CSS classes merged into the root <div> wrapper. Defaults to nil.

  • disabled (:boolean) - Forwarded to the underlying multi_select/1 to disable the select. Defaults to false.

multi_select(assigns)

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) - HTML id attribute for the underlying <select> element.

  • name (:string) (required) - Base name attribute. The component automatically appends [] to produce name[], so all selected values are submitted as an array.

  • options (:list) - List of {label, value} tuples to render as <option> elements. label is the human-readable text; value is the submitted form value.

    Defaults to [].

  • selected (:list) - List of currently selected values (strings). Options whose value appears in this list are rendered with the selected attribute and displayed as removable chips above the select.

    Defaults to [].

  • placeholder (:string) - Placeholder text used as the aria-label of 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 receives phx-value-deselect with the value being removed.

    Defaults to nil.

  • class (:string) - Additional Tailwind CSS classes merged into the root <div> wrapper via cn/1. Defaults to nil.

  • disabled (:boolean) - When true, the <select> element is rendered with the disabled attribute. Defaults to false.