Phoenix Form
<.form
for={@form}
action={~p"/slider/form"}
method="post"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.slider
field={@form[:volume]}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.slider>
<.action type="submit" class="button ui-accent">Submit</.action>
</.form>
def slider_form_page(conn, _params) do
phoenix_form =
Phoenix.Component.to_form(%{"volume" => "0"}, as: :slider_phoenix, id: "slider-form-phoenix")
render(conn, :slider_form_page, phoenix_form: phoenix_form)
end
def slider_form_submit(conn, params) do
if is_map(params["slider_phoenix"]) do
volume = params["slider_phoenix"]["volume"] || ""
conn
|> put_flash(:info, "Submitted: volume=#{inspect(volume)}")
|> redirect(to: ~p"/slider/form#slider-form-phoenix")
end
end
Phoenix Form · Range
<.form
for={@form}
action={~p"/slider/form"}
method="post"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.slider
field={@form[:volume]}
value={[20, 80]}
min_steps_between_thumbs={1}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume</:label>
</.slider>
<.action type="submit" class="button ui-accent">Submit</.action>
</.form>
def slider_form_page(conn, _params) do
phoenix_range_form =
Phoenix.Component.to_form(%{"volume" => ["20", "80"]},
as: :slider_phoenix_range,
id: "slider-form-phoenix-range"
)
render(conn, :slider_form_page, phoenix_range_form: phoenix_range_form)
end
def slider_form_submit(conn, %{"slider_phoenix_range" => params}) do
volume = params["volume"] || []
conn
|> put_flash(:info, "Submitted: volume=#{inspect(volume)}")
|> redirect(to: ~p"/slider/form#slider-form-phoenix-range")
end
Phoenix Form + Ecto
<.form
for={@form}
action={~p"/slider/form"}
method="post"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.slider
field={@form[:volume]}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume (over 90)</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.slider>
<.action type="submit" class="button ui-accent">Submit</:action>
</.form>
def product_form_validated_page(conn, _params) do
changeset =
MyApp.Forms.Slider.changeset_validate(%MyApp.Forms.Slider{}, %{})
form =
Phoenix.Component.to_form(changeset,
as: :slider_validated,
id: "product-volume-validated-form"
)
render(conn, :product_form_validated, form: form)
end
def product_form_validated_create(conn, %{"slider_validated" => params}) do
case MyApp.Forms.Slider.changeset_validate(%MyApp.Forms.Slider{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
data = Ecto.Changeset.apply_changes(changeset)
conn
|> put_flash(:info, "Saved volume=#{data.volume}")
|> redirect(to: ~p"/products")
changeset ->
changeset = Map.put(changeset, :action, :insert)
form =
Phoenix.Component.to_form(changeset,
as: :slider_validated,
id: "product-volume-validated-form"
)
render(conn, :product_form_validated, form: form)
end
end
defmodule MyApp.Forms.Slider do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :volume, :float
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:volume])
|> validate_required([:volume])
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:volume])
|> validate_required([:volume])
|> validate_number(:volume,
greater_than: 90.0,
message: "must be over 90"
)
end
end
Phoenix Form + Ecto · Range
<.form
for={@form}
action={~p"/slider/form"}
method="post"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.slider
field={@form[:volume]}
value={[20, 80]}
min_steps_between_thumbs={1}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume (high over 90)</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.slider>
<.action type="submit" class="button ui-accent">Submit</:action>
</.form>
def product_form_validated_page(conn, _params) do
changeset =
MyApp.Forms.SliderRange.changeset_validate(%MyApp.Forms.SliderRange{}, %{})
form =
Phoenix.Component.to_form(changeset,
as: :slider_validated_range,
id: "product-volume-validated-range-form"
)
render(conn, :product_form_validated_range, form: form)
end
def product_form_validated_range_create(conn, %{"slider_validated_range" => params}) do
case MyApp.Forms.SliderRange.changeset_validate(%MyApp.Forms.SliderRange{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
data = Ecto.Changeset.apply_changes(changeset)
conn
|> put_flash(:info, "Saved volume=#{inspect(data.volume)}")
|> redirect(to: ~p"/products")
changeset ->
changeset = Map.put(changeset, :action, :insert)
form =
Phoenix.Component.to_form(changeset,
as: :slider_validated_range,
id: "product-volume-validated-range-form"
)
render(conn, :product_form_validated_range, form: form)
end
end
defmodule MyApp.Forms.SliderRange do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :volume, {:array, :float}
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:volume])
|> validate_required([:volume])
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:volume])
|> validate_required([:volume])
|> validate_length(:volume, is: 2, message: "must have two values")
|> validate_high_over_90()
end
defp validate_high_over_90(changeset) do
case get_field(changeset, :volume) do
[_, high] when is_number(high) and high > 90 ->
changeset
[_, _high] ->
add_error(changeset, :volume, "must be over 90")
_ ->
changeset
end
end
end
Native HTML Form
<form
action={~p"/slider/form"}
method="post"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<.slider
name="slider_form[volume]"
value={0.0}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume</:label>
</.slider>
<.action type="submit" class="button ui-accent">Submit</:action>
</form>
def slider_form_submit(conn, %{"slider_form" => %{"volume" => volume}}) do
conn
|> put_flash(:info, "Submitted: volume=#{volume}")
|> redirect(to: ~p"/slider/form#slider-form-native")
end
Native HTML Form · Range
<form action={~p"/slider/form"} method="post" class="flex flex-col gap-space-lg w-full max-w-xl">
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<.slider
name="slider_form_range[volume]"
value={[20, 80]}
min_steps_between_thumbs={1}
markers marker_values={[0, 25, 50, 75, 100]}
class="slider"
>
<:label>Volume</:label>
</.slider>
<.action type="submit" class="button ui-accent">Submit</.action>
</form>
def slider_form_submit(conn, %{"slider_form_range" => %{"volume" => volume}}) do
conn
|> put_flash(:info, "Submitted: volume=#{inspect(volume)}")
|> redirect(to: ~p"/slider/form")
end