Select · Pattern
Controlled selection and stream-driven items.
Controlled
Country
- France
- Belgium
- Germany
- Netherlands
- Switzerland
- Austria
<.select
class="select"
controlled
value={@value}
items={@items}
on_value_change="value_changed"
>
<:label>Country</:label>
<:trigger>
<.heroicon name="hero-chevron-down" class="icon" />
</:trigger>
</.select>
def mount(_params, _session, socket) do
items =
Corex.List.new([
%{label: "France", value: "fra"},
%{label: "Belgium", value: "bel"},
%{label: "Germany", value: "deu"},
%{label: "Netherlands", value: "nld"},
%{label: "Switzerland", value: "che"},
%{label: "Austria", value: "aut"}
])
{:ok, assign(socket, value: [], items: items)}
end
def handle_event("value_changed", %{"value" => value}, socket) do
{:noreply, assign(socket, :value, value)}
end
Stream
Country
- Lorem ipsum dolor sit amet
- Duis dictum gravida odio ac pharetra?
- Donec condimentum ex mi
<div class="flex flex-col gap-3 w-full max-w-xl">
<div class="flex flex-wrap gap-2">
<.action phx-click="add_item" class="button button--sm button--accent">
<.heroicon name="hero-plus" /> Add item
</.action>
<.action phx-click="reset" class="button button--sm button--alert">
Reset
</.action>
</div>
<.select class="select" items={Corex.List.new(@items_list)}>
<:label>Country</:label>
<:trigger>
<.heroicon name="hero-chevron-down" class="icon" />
</:trigger>
</.select>
</div>
defmodule MyAppWeb.SelectStreamDemoLive do
use MyAppWeb, :live_view
@impl true
def mount(_params, _session, socket) do
initial = [
%{value: "lorem", label: "Lorem ipsum dolor sit amet"},
%{value: "duis", label: "Duis dictum gravida odio ac pharetra?"},
%{value: "donec", label: "Donec condimentum ex mi"}
]
{:ok,
socket
|> stream_configure(:items, dom_id: &("select:stream-select:item:" <> &1.value))
|> stream(:items, initial)
|> assign(:items_list, initial)
|> assign(:next_id, 1)}
end
@impl true
def handle_event("add_item", _params, socket) do
id = "item-#{socket.assigns.next_id}"
item = %{value: id, label: "Item #{socket.assigns.next_id}"}
{:noreply,
socket
|> stream_insert(:items, item)
|> assign(:items_list, socket.assigns.items_list ++ [item])
|> assign(:next_id, socket.assigns.next_id + 1)}
end
@impl true
def handle_event("reset", _params, socket) do
initial = [
%{value: "lorem", label: "Lorem ipsum dolor sit amet"},
%{value: "duis", label: "Duis dictum gravida odio ac pharetra?"},
%{value: "donec", label: "Donec condimentum ex mi"}
]
{:noreply,
socket
|> stream(:items, initial, reset: true)
|> assign(:items_list, initial)
|> assign(:next_id, 1)}
end
@impl true
def render(assigns) do
~H"""
<div class="flex flex-col gap-3 w-full max-w-xl">
<div class="flex flex-wrap gap-2">
<.action phx-click="add_item" class="button button--sm button--accent">
<.heroicon name="hero-plus" /> Add item
</.action>
<.action phx-click="reset" class="button button--sm button--alert">
Reset
</.action>
</div>
<.select id="stream-select" class="select" items={Corex.List.new(@items_list)}>
<:label>Country</:label>
<:trigger>
<.heroicon name="hero-chevron-down" class="icon" />
</:trigger>
</.select>
</div>
"""
end
end