Simple Form

Full Screen Demo

A simple form showing how to use Phoenix LiveView with Petal Components. This uses forms v2.

defmodule PetalProWeb.SimpleFormLive do
use PetalProWeb, :live_view
@impl true
def mount(_params, _session, socket) do
changeset = build_changeset()
{:ok, socket |> assign(submission: nil) |> assign_form(changeset)}
end
@impl true
def handle_event("validate", %{"object" => object_params}, socket) do
changeset =
object_params
|> build_changeset()
|> Map.put(:action, :validate)
{:noreply, assign_form(socket, changeset)}
end
@impl true
def handle_event("submit", %{"object" => object_params}, socket) do
changeset = build_changeset(object_params)
case validate_changeset(changeset) do
{:ok, submission} ->
socket =
socket
|> put_flash(:success, "Object successfully created")
|> assign_form(build_changeset())
|> assign(submission: submission)
{:noreply, socket}
{:error, changeset} ->
socket =
socket
|> put_flash(:error, inspect(changeset.errors))
{:noreply, assign_form(socket, changeset)}
end
end
defp assign_form(socket, changeset) do
assign(socket, form: to_form(changeset, as: :object))
end
defp build_changeset(params \\ %{}) do
data = %{}
types = %{
text: :string,
select: :string,
checkbox_group: {:array, :string},
radio_group: :string,
textarea: :string,
checkbox: :boolean,
color: :string,
date: :date,
datetime_local: :naive_datetime,
email: :string,
file: :string,
hidden: :string,
month: :string,
number: :integer,
password: :string,
radio: :string,
range: :integer,
search: :string,
tel: :string,
time: :time,
url: :string,
week: :string,
switch: :boolean
}
{data, types}
|> Ecto.Changeset.cast(params, Map.keys(types))
|> Ecto.Changeset.validate_required([:text])
|> Ecto.Changeset.validate_acceptance(:checkbox)
|> Ecto.Changeset.validate_length(:text, min: 3, max: 50)
end
defp validate_changeset(changeset) do
Ecto.Changeset.apply_action(changeset, :validate)
end
end
<.container max_width="md" class="mx-auto my-20">
<.h2>Simple form</.h2>
<.form for={@form} phx-submit="submit" phx-change="validate">
<.field type="text" field={@form[:text]} placeholder="Text" phx-debounce="blur" label="Text*" />
<.field type="checkbox" field={@form[:checkbox]} label="Check me*" />
<.field type="select" field={@form[:select]} options={["Option 1", "Option 2", "Option 3"]} />
<.field
type="checkbox-group"
field={@form[:checkbox_group]}
options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>
<.field
type="radio-group"
field={@form[:radio_group]}
group_layout="row"
options={[{"Option 1", "1"}, {"Option 2", "2"}, {"Option 3", "3"}]}
/>
<.field type="switch" field={@form[:switch]} />
<.field type="color" field={@form[:color]} />
<.field type="date" field={@form[:date]} />
<.field type="datetime-local" field={@form[:datetime_local]} />
<.field type="email" field={@form[:email]} />
<.field type="file" field={@form[:file]} />
<.field type="hidden" field={@form[:hidden]} />
<.field type="month" field={@form[:month]} />
<.field type="number" field={@form[:number]} />
<.field type="password" field={@form[:password]} />
<.field type="range" field={@form[:range]} />
<.field type="search" field={@form[:search]} />
<.field type="tel" field={@form[:tel]} />
<.field type="time" field={@form[:time]} />
<.field type="url" field={@form[:url]} />
<.field type="week" field={@form[:week]} />
<div class="flex justify-end">
<.button>Submit</.button>
</div>
<div :if={@submission} class="mt-4">
<.h3>Submitted params:</.h3>
<%= inspect(@submission) %>
</div>
</.form>
</.container>
live(
"/recipes/forms/examples/simple-form",
SimpleFormLive,
:index
)