Editable · Form
Phoenix Form
<.form
for={@form}
action={~p"/editable/form"}
method="post"
>
<.editable field={@form[:text]} placeholder="Enter text" activation_mode="dblclick" select_on_focus class="editable">
<:label>Text</:label>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
</.editable>
<.action type="submit" class="button button--accent">Submit</.action>
</.form>
def editable_form_page(conn, _params) do
phoenix_form =
Phoenix.Component.to_form(%{"text" => ""}, as: :editable_phoenix, id: "editable-form-phoenix")
render(conn, :editable_form_page, phoenix_form: phoenix_form)
end
def editable_form_submit(conn, params) do
if is_map(params["editable_phoenix"]) do
text = params["editable_phoenix"]["text"] || ""
conn
|> put_flash(:info, "Submitted: text=#{inspect(text)}")
|> redirect(to: ~p"/editable/form#editable-form-phoenix")
end
end
Phoenix Form + Ecto
<.form
for={@form}
action={~p"/editable/form"}
method="post"
>
<.editable field={@form[:text]} placeholder="Enter text" activation_mode="dblclick" select_on_focus class="editable">
<:label>Text</:label>
<:error :let={msg}>
<.heroicon name="hero-exclamation-circle" class="icon" />
{msg}
</:error>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>
<.action type="submit" class="button button--accent">Submit</.action>
</.form>
def editable_form_page(conn, _params) do
ecto_form =
%MyApp.Form.EditableForm{}
|> MyApp.Form.EditableForm.changeset(%{})
|> Phoenix.Component.to_form(as: :editable_ecto, id: "editable-form-ecto")
render(conn, :editable_form_page, ecto_form: ecto_form)
end
def editable_form_submit(conn, params) do
if is_map(params["editable_ecto"]) do
case MyApp.Form.EditableForm.changeset(%MyApp.Form.EditableForm{}, params["editable_ecto"]) do
%Ecto.Changeset{valid?: true} = changeset ->
data = Ecto.Changeset.apply_changes(changeset)
conn
|> put_flash(:info, "Submitted: text=#{inspect(data.text)}")
|> redirect(to: ~p"/editable/form#editable-form-ecto")
changeset ->
changeset = Map.put(changeset, :action, :insert)
ecto_form = Phoenix.Component.to_form(changeset, as: :editable_ecto, id: "editable-form-ecto")
render(conn, :editable_form_page, ecto_form: ecto_form)
end
end
end
defmodule MyApp.Form.EditableForm do
use Ecto.Schema
import Ecto.Changeset
embedded_schema do
field :text, :string
end
def changeset(form, attrs \\ %{}) do
form
|> cast(attrs, [:text])
|> validate_required([:text], message: "can't be blank")
end
end
Native HTML Form
<form action={~p"/editable/form"} method="post">
<input type="hidden" name="_csrf_token" value={Plug.CSRFProtection.get_csrf_token()} />
<.editable name="editable[text]" value="" placeholder="Enter text" activation_mode="dblclick" select_on_focus class="editable">
<:label>Text</:label>
<:edit_trigger><.heroicon name="hero-pencil-square" class="icon" /></:edit_trigger>
<:submit_trigger><.heroicon name="hero-check" class="icon" /></:submit_trigger>
<:cancel_trigger><.heroicon name="hero-x-mark" class="icon" /></:cancel_trigger>
</.editable>
<.action type="submit" class="button button--accent">Submit</.action>
</form>
def editable_form_submit(conn, %{"editable" => %{"text" => text}}) do
conn
|> put_flash(:info, "Submitted: text=#{inspect(text)}")
|> redirect(to: ~p"/editable/form#editable-form-native")
end