Phoenix Form
<.form for={@form} phx-submit="save_phoenix"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.switch field={@form[:notifications]} class="switch">
<:label>Enable notifications</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.switch>
<.action type="submit" class="button ui-accent">
Submit
</.action>
</.form>
defmodule MyAppWeb.SwitchFormLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
phoenix_form =
Phoenix.Component.to_form(%{"notifications" => false},
as: :preferences_phoenix,
id: "switch-live-form-phoenix"
)
{:ok, assign(socket, :phoenix_form, phoenix_form)}
end
def handle_event("save_phoenix", %{"preferences_phoenix" => params}, socket) do
notifications = params["notifications"] in [true, "true", "on", "1", 1]
{:noreply,
assign(
socket,
:phoenix_form,
Phoenix.Component.to_form(%{"notifications" => notifications},
as: :preferences_phoenix,
id: "switch-live-form-phoenix"
)
)}
end
end
Phoenix Form + Ecto
<.form for={@form} phx-change="validate" phx-submit="save"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.switch field={@form[:notifications]} class="switch">
<:label>Enable notifications</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.switch>
<.action type="submit" class="button ui-accent">
Submit
</.action>
</.form>
defmodule MyAppWeb.SwitchFormLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
ecto_form =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(%{})
|> Phoenix.Component.to_form(as: :preferences_ecto, id: "switch-live-form-ecto")
{:ok, assign(socket, :ecto_form, ecto_form)}
end
def handle_event("validate", %{"preferences_ecto" => params}, socket) do
changeset =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(params)
|> Map.put(:action, :validate)
{:noreply,
assign(
socket,
:ecto_form,
Phoenix.Component.to_form(changeset,
action: :validate,
as: :preferences_ecto,
id: "switch-live-form-ecto"
)
)}
end
def handle_event("save", %{"preferences_ecto" => params}, socket) do
case MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
{:noreply,
assign(
socket,
:ecto_form,
Phoenix.Component.to_form(
MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params),
as: :preferences_ecto,
id: "switch-live-form-ecto"
)
)}
changeset ->
{:noreply,
assign(
socket,
:ecto_form,
Phoenix.Component.to_form(changeset,
action: :insert,
as: :preferences_ecto,
id: "switch-live-form-ecto"
)
)}
end
end
end
defmodule MyApp.Forms.Preferences do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :notifications, :boolean, default: false
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications)
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications, message: "must be accepted to continue")
end
end
Phoenix Form + Ecto + Controlled
<.form for={@ecto_controlled_form} phx-change="validate_controlled" phx-submit="save_controlled"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.switch
field={@ecto_controlled_form[:notifications]}
class="switch"
id="switch-live-form-ecto-controlled-notifications"
controlled
>
<:label>Enable notifications</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.switch>
<.action type="submit" id="switch-live-form-ecto-controlled-submit" class="button ui-accent">
Submit
</.action>
</.form>
defmodule MyAppWeb.SwitchFormLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
ecto_controlled_form =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(%{})
|> Phoenix.Component.to_form(as: :preferences_ecto_controlled, id: "switch-live-form-ecto-controlled")
{:ok, assign(socket, :ecto_controlled_form, ecto_controlled_form)}
end
def handle_event("validate_controlled", %{"preferences_ecto_controlled" => params}, socket) do
validate_ecto_controlled(socket, params)
end
def handle_event("save_controlled", %{"preferences_ecto_controlled" => params}, socket) do
case MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
_data = Ecto.Changeset.apply_changes(changeset)
{:noreply,
assign(
socket,
:ecto_controlled_form,
Phoenix.Component.to_form(
MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params),
as: :preferences_ecto_controlled,
id: "switch-live-form-ecto-controlled"
)
)}
changeset ->
{:noreply,
assign(
socket,
:ecto_controlled_form,
Phoenix.Component.to_form(changeset,
action: :insert,
as: :preferences_ecto_controlled,
id: "switch-live-form-ecto-controlled"
)
)}
end
end
defp validate_ecto_controlled(socket, params) do
changeset =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(params)
|> Map.put(:action, :validate)
{:noreply,
assign(
socket,
:ecto_controlled_form,
Phoenix.Component.to_form(changeset,
action: :validate,
as: :preferences_ecto_controlled,
id: "switch-live-form-ecto-controlled"
)
)}
end
end
defmodule MyApp.Forms.Preferences do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :notifications, :boolean, default: false
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications)
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications, message: "must be accepted to continue")
end
end
Phoenix Form + Ecto + Invalid
<.form for={@ecto_invalid_form} phx-change="validate_invalid" phx-submit="save_invalid"
class="flex flex-col gap-space-lg w-full max-w-xl"
>
<.switch
field={@ecto_invalid_form[:notifications]}
class="switch"
id="switch-live-form-ecto-invalid-notifications"
invalid={Corex.FormField.invalid?(@ecto_invalid_form[:notifications])}
>
<:label>Enable notifications</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.switch>
<.action type="submit" id="switch-live-form-ecto-invalid-submit" class="button ui-accent">
Submit
</.action>
</.form>
defmodule MyAppWeb.SwitchFormLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
ecto_invalid_form =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(%{})
|> Phoenix.Component.to_form(as: :preferences_ecto_invalid, id: "switch-live-form-ecto-invalid")
{:ok, assign(socket, :ecto_invalid_form, ecto_invalid_form)}
end
def handle_event("validate_invalid", %{"preferences_ecto_invalid" => params}, socket) do
validate_ecto_invalid(socket, params)
end
def handle_event("save_invalid", %{"preferences_ecto_invalid" => params}, socket) do
case MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params) do
%Ecto.Changeset{valid?: true} = changeset ->
_data = Ecto.Changeset.apply_changes(changeset)
{:noreply,
assign(
socket,
:ecto_invalid_form,
Phoenix.Component.to_form(
MyApp.Forms.Preferences.changeset_validate(%MyApp.Forms.Preferences{}, params),
as: :preferences_ecto_invalid,
id: "switch-live-form-ecto-invalid"
)
)}
changeset ->
{:noreply,
assign(
socket,
:ecto_invalid_form,
Phoenix.Component.to_form(changeset,
action: :insert,
as: :preferences_ecto_invalid,
id: "switch-live-form-ecto-invalid"
)
)}
end
end
defp validate_ecto_invalid(socket, params) do
changeset =
%MyApp.Forms.Preferences{}
|> MyApp.Forms.Preferences.changeset_validate(params)
|> Map.put(:action, :validate)
{:noreply,
assign(
socket,
:ecto_invalid_form,
Phoenix.Component.to_form(changeset,
action: :validate,
as: :preferences_ecto_invalid,
id: "switch-live-form-ecto-invalid"
)
)}
end
end
defmodule MyApp.Forms.Preferences do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :notifications, :boolean, default: false
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications)
end
def changeset_validate(form, attrs \\ %{}) do
form
|> cast(attrs, [:notifications])
|> validate_acceptance(:notifications, message: "must be accepted to continue")
end
end