View Source LiveSelect (LiveSelect v0.4.0)
The LiveSelect
component is rendered by calling the live_select/3
function and passing it a form and the name of the field.
LiveSelect creates a text input field in which the user can type text, and hidden input field(s) that will contain the value of the selected option(s).
As the input text changes, LiveSelect will render a dropdown below the text input containing the matching options, which the user can then select.
Selection can happen either using the keyboard, by navigating the options with the arrow keys and then pressing enter, or by clicking an option with the mouse.
Whenever an option is selected, LiveSelect
will trigger a standard phx-change
event in the form. See the "Examples" section
below for details on how to handle the event.
In single mode, if the configuration option allow_clear
is set, the user can manually clear the selection by clicking on the x
button on the input field.
In tags mode, single tags can be removed by clicking on them.
single-mode
Single mode

tags-mode
Tags mode

options
Options
You can pass or update the list of options the user can choose from with the options
assign.
Each option will be assigned a label, which will be shown in the dropdown, and a value, which will be the value of the
LiveSelect input when the option is selected.
options
can be any enumeration of the following elements:
- atoms, strings or numbers: In this case, each element will be both label and value for the option
- tuples:
{label, value}
corresponding to label and value for the option - maps:
%{label: label, value: value}
or%{value: value}
- keywords:
[label: label, value: value]
or[value: value]
In the case of maps and keywords, if only value
is specified, it will be used as both value and label for the option.
Because you can pass a list of tuples, you can use maps and keyword lists to pass the list of options, for example:
%{Red: 1, Yellow: 2, Green: 3}
Will result in 3 options with labels :Red
, :Yellow
, :Green
and values 1, 2, and 3.
Note that the option values, if they are not strings, will be JSON-encoded. Your LiveView will receive this JSON-encoded version in the phx-change
and phx-submit
events.
alternative-tag-labels
Alternative tag labels
Sometimes, in :tags
mode, you might want to use alternative labels for the tags. For example, you might want the labels in the tags to be shorter
in order to save space. You can do this by specifying an additional tag_label
key when passing options as map or keywords. For example, passing these options:
[%{label: "New York", tag_label: "NY"}, %{label: "Barcelona", tag_label: "BCN"}]
will result in "New York" and "Barcelona" being used for the options in the dropdown, while "NY" and "BCN" will be used for the tags.
reacting-to-user-s-input
Reacting to user's input
Whenever the user types something in the text input, LiveSelect sends a LiveSelect.ChangeMsg.t/0
message to your LiveView.
The message has a text
property containing the current text entered by the user, as well as id
and field
properties with the id of the
LiveSelect component and the name of the LiveSelect form field, respectively.
The LiveView's job is to handle_info/2
the message and then call LiveView.send_update/3
to update the list of selectable options. See the "Examples" section below for details.
multiple-selection-with-tags-mode
Multiple selection with tags mode
When :tags
mode is enabled LiveSelect
allows the user to select multiple entries. The entries will be visible above the text input field as removable tags.
The selected entries will be passed to your live view's change
and submit
event handlers as a list of entries, just like an HTML <select> element with multiple attribute would do.
clearing-the-selection-programmatically
Clearing the selection programmatically
You can clear the selection programmatically by sending a clear: true
assign to LiveSelect
send_update(LiveSelect.Component, id: live_select_id, clear: true)
To set a custom id for the component, use the id
option when calling live_select/3
.
examples
Examples
These examples describe all the moving parts in detail. You can see these examples in action, see which messages and events are being sent, and play around with the configuration easily with the showcase app.
single-mode-1
Single mode
The user can search for cities.
The LiveSelect main form input is called city_search
.
When a city is selected, the coordinates of that city will be the value of the form input.
The name of the selected city is available in the text input field named city_search_text_input
.
Template:
<.form for={:my_form} :let={f} phx-change="change">
<%= live_select f, :city_search %>
</.form>
LiveView:
import LiveSelect
@impl true
def handle_info(%LiveSelect.ChangeMsg{} = change_msg, socket) do
cities = City.search(change_msg.text)
# cities could be:
# [ {"city name 1", [lat_1, long_1]}, {"city name 2", [lat_2, long_2]}, ... ]
#
# but it could also be (no coordinates in this case):
# [ "city name 1", "city name 2", ... ]
#
# or:
# [ [label: "city name 1", value: [lat_1, long_1]], [label: "city name 2", value: [lat_2, long_2]], ... ]
#
# or even:
# ["city name 1": [lat_1, long_1], "city name 2": [lat_2, long_2]]
send_update(LiveSelect.Component, id: change_msg.id, options: cities)
{:noreply, socket}
end
@impl true
def handle_event(
"change",
%{"my_form" => %{"city_search_text_input" => city_name, "city_search" => city_coords}},
socket
) do
IO.puts("You selected city #{city_name} located at: #{city_coords}")
{:noreply, socket}
end
tags-mode-1
Tags mode
Let's say you want to build on the previous example and allow the user to select multiple cities and not only one.
The :tags
mode allows you to do exactly this.
Template:
<.form for={:my_form} :let={f} phx-change="change">
<%= live_select f, :city_search, mode: :tags %>
</.form>
LiveView:
@impl true
def handle_event(
"change",
%{"my_form" => %{"city_search" => list_of_coords}},
socket
) do
# list_of_coords will contain the list of the JSON-encoded coordinates of the selected cities, for example:
# ["[-46.565,-23.69389]", "[-48.27722,-18.91861]"]
IO.puts("You selected cities located at: #{list_of_coords}")
{:noreply, socket}
end
multiple-liveselect-inputs-in-the-same-liveview
Multiple LiveSelect inputs in the same LiveView
If you have multiple LiveSelect inputs in the same LiveView, you can distinguish them based on the field or id. For example:
Template:
<.form for={:my_form} :let={f} phx-change="change">
<%= live_select f, :city_search %>
<%= live_select f, :album_search %>
</.form>
LiveView:
@impl true
def handle_info(%LiveSelect.ChangeMsg{} = change_msg, socket) do
options =
case change_msg.field do
:city_search -> City.search(change_msg.text)
:album_search -> Album.search(change_msg.text)
end
send_update(LiveSelect.Component, id: change_msg.id, options: options)
{:noreply, socket}
end
Link to this section Summary
Functions
Renders a LiveSelect
input in a form
with a given field
name.
Updates a LiveSelect
component with new options. change_msg
must be the LiveSelect.ChangeMsg.t/0
originally sent by the LiveSelect,
and options
is the new list of options that will be used to fill the dropdown.
Link to this section Functions
Renders a LiveSelect
input in a form
with a given field
name.
LiveSelect renders two inputs: a hidden input (of type either text or select, depending on the specified mode) named field
that holds the value of the selected option(s),
and a visible text input field named #{field}_text_input
that contains the text entered by the user.
Opts:
id
- an id to assign to the component. If none is provided,#{form_name}_#{field_name}_component
will be usedmode
- either:single
(for single selection, the default), or:tags
(for multiple selection using tags)options
- initial available options to select from. See the "Options" section for details on what you can pass herevalue
- used to manually set an initial selection - overrides any values from the form. Must be a single element in:single
mode, or a list of elements in:tags
mode. If an element can be found in the initial options, the corresponding label will be used. Otherwise, the element will be used for both value and labelmax_selectable
- limits the maximum number of selectable elements. Defaults to0
, meaning no limituser_defined_options
- iftrue
, hitting enter will always add the text entered by the user to the selection. Defaults tofalse
allow_clear
- iftrue
, when in single mode, display a "x" button in the input field to clear the selectiondisabled
- set this totrue
to disable the input fieldplaceholder
- placeholder text for the input fielddebounce
- number of milliseconds to wait after the last keystroke before sending aLiveSelect.ChangeMsg.t/0
message. Defaults to 100msupdate_min_len
- the minimum length of text in the text input field that will trigger an update of the dropdown. It has to be a positive integer. Defaults to 3style
- one of:tailwind
(the default),:daisyui
or:none
. See the Styling section for detailsactive_option_class
,available_option_class
,container_class
,container_extra_class
,dropdown_class
,dropdown_extra_class
,option_class
,option_extra_class
,text_input_class
,text_input_extra_class
,text_input_selected_class
,selected_option_class
,tag_class
,tag_extra_class
,tags_container_class
,tags_container_extra_class
- see the Styling section for details
Updates a LiveSelect
component with new options. change_msg
must be the LiveSelect.ChangeMsg.t/0
originally sent by the LiveSelect,
and options
is the new list of options that will be used to fill the dropdown.