Radio Group · Pattern
Controlled selection and stream-driven items.
Controlled
Choose one
<.radio_group
name="patterns-rg"
class="radio-group"
items={[
%{value: "lorem", label: "Lorem ipsum dolor sit amet"},
%{value: "duis", label: "Duis dictum gravida odio ac pharetra?"},
%{value: "donec", label: "Donec condimentum ex mi"}
]}
value={@value}
controlled
on_value_change="patterns_radio_value"
>
<:label>Choose one</:label>
<:item_control><.heroicon name="hero-check" class="data-checked" /></:item_control>
</.radio_group>
def mount(_params, _session, socket) do
{:ok, assign(socket, :value, "lorem")}
end
def handle_event("patterns_radio_value", %{"value" => v}, socket) do
{:noreply, assign(socket, :value, v)}
end
Stream
Choose one
<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>
<.radio_group
name="stream-rg"
class="radio-group"
items={@items_list}
value={@stream_value}
controlled
on_value_change="patterns_stream_value"
>
<:label>Choose one</:label>
<:item_control><.heroicon name="hero-check" class="data-checked" /></:item_control>
</.radio_group>
</div>
defmodule MyAppWeb.RadioGroupStreamDemoLive 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"}
]
socket =
socket
|> stream_configure(:items, dom_id: &("radio-group:stream-radio-group:item:" <> &1.value))
|> stream(:items, initial)
|> assign(:items_list, initial)
|> assign(:stream_value, "lorem")
|> assign(:next_id, 1)
{:ok, socket}
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(:stream_value, "lorem")
|> assign(:next_id, 1)}
end
@impl true
def handle_event("patterns_stream_value", %{"value" => v}, socket) do
{:noreply, assign(socket, :stream_value, v)}
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>
<.radio_group
id="stream-radio-group"
name="stream-rg"
class="radio-group"
items={@items_list}
value={@stream_value}
controlled
on_value_change="patterns_stream_value"
>
<:label>Choose one</:label>
<:item_control><.heroicon name="hero-check" class="data-checked" /></:item_control>
</.radio_group>
</div>
"""
end
end