Angle Slider · Form
Phoenix Form
<.form
for={@form}
action={~p"/angle-slider/form"}
method="post"
>
<.angle_slider
field={@form[:angle]}
marker_values={[0, 90, 180, 270]}
class="angle-slider"
>
<:label>Angle</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.angle_slider>
<.action type="submit" class="button button--accent">Submit</.action>
</.form>
def angle_slider_form_page(conn, _params) do
phoenix_form =
Phoenix.Component.to_form(%{"angle" => "0"}, as: :angle_slider_phoenix, id: "angle-slider-form-phoenix")
render(conn, :angle_slider_form_page, phoenix_form: phoenix_form)
end
def angle_slider_form_submit(conn, params) do
if is_map(params["angle_slider_phoenix"]) do
angle = params["angle_slider_phoenix"]["angle"] || ""
conn
|> put_flash(:info, "Submitted: angle=#{inspect(angle)}")
|> redirect(to: ~p"/angle-slider/form#angle-slider-form-phoenix")
end
end
Phoenix Form + Ecto
<.form
for={@form}
action={~p"/angle-slider/form"}
method="post"
>
<.angle_slider
field={@form[:angle]}
marker_values={[0, 90, 180, 270]}
class="angle-slider"
>
<:label>Angle (0–90)</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.angle_slider>
<.action type="submit" class="button button--accent">Submit</:action>
</.form>
def product_form_validated_page(conn, _params) do
changeset =
MyApp.Forms.AngleSlider.changeset_validate(%MyApp.Forms.AngleSlider{}, %{})
form =
Phoenix.Component.to_form(changeset,
as: :angle_slider_validated,
id: "product-angle-validated-form"
)
render(conn, :product_form_validated, form: form)
end
def product_form_validated_create(conn, %{"angle_slider_validated" => params}) do
case MyApp.Forms.AngleSlider.changeset_validate(%MyApp.Forms.AngleSlider{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
data = Ecto.Changeset.apply_changes(changeset)
conn
|> put_flash(:info, "Saved angle=#{data.angle}")
|> redirect(to: ~p"/products")
changeset ->
changeset = Map.put(changeset, :action, :insert)
form =
Phoenix.Component.to_form(changeset,
as: :angle_slider_validated,
id: "product-angle-validated-form"
)
render(conn, :product_form_validated, form: form)
end
end
defmodule MyApp.Forms.AngleSlider do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :angle, :float, default: 0.0
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:angle])
|> validate_required([:angle])
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:angle])
|> validate_required([:angle])
|> validate_number(:angle,
greater_than_or_equal_to: 0.0,
less_than_or_equal_to: 90.0,
message: "must be between 0 and 90"
)
end
end
Native HTML Form
<form
action={~p"/angle-slider/form"}
method="post"
>
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<.angle_slider
name="angle_slider_form[angle]"
value={0.0}
marker_values={[0, 90, 180, 270]}
class="angle-slider"
>
<:label>Angle</:label>
</.angle_slider>
<.action type="submit" class="button button--accent">Submit</:action>
</form>
def angle_slider_form_submit(conn, %{"angle_slider_form" => %{"angle" => angle}}) do
conn
|> put_flash(:info, "Submitted: angle=#{angle}")
|> redirect(to: ~p"/angle-slider/form#angle-slider-form-native")
end