OK, I whipped up an implementation based on some of the examples found in the generated code created while I was working on the project. I don’t know if it’s better. All I know is that it works, it matches the style of the generated code (which I assume is reasonably relevant), and it matches the info I found on this LiveView docs page that I referenced in my original post.
lib/pento_web/live/promo_live.ex
defmodule PentoWeb.PromoLive do
use PentoWeb, :live_view
alias Pento.Promo
alias Pento.Promo.Recipient
@impl true
def mount(_params, _session, socket) do
changeset = Promo.change_recipient(%Recipient{})
{:ok, socket |> assign_form(changeset)}
end
defp assign_form(socket, %Ecto.Changeset{} = changeset) do
assign(socket, :form, to_form(changeset))
end
@impl true
def handle_event("validate", %{"recipient" => recipient_params}, socket) do
changeset = %Recipient{}
|> Promo.change_recipient(recipient_params)
|> Map.put(:action, :validate)
{:noreply, assign_form(socket, changeset)}
end
def handle_event("save", %{"recipient" => recipient_params}, socket) do
changeset = %Recipient{}
|> Promo.change_recipient(recipient_params)
if changeset.valid? do
{:noreply, socket |> put_flash(:info, "Form submitted successfully.")}
else
{:noreply,
socket
|> put_flash(:error, "Please fill out the form correctly before continuing.")}
end
end
end
lib/pento_web/live/promo_live.html.heex
<.header>
Send Your Promo Code to a Friend
<:subtitle>promo code for 10% off their first game purchase!</:subtitle>
</.header>
<.simple_form
for={@form}
id="promo-form"
phx-change="validate"
phx-submit="save"
>
<.input field={@form[:first_name]} type="text" label="First name" />
<.input field={@form[:email]} type="email" label="Email address" phx-debounce="blur" />
<:actions>
<.button phx-disable-with="Sending...">Send Promo</.button>
</:actions>
</.simple_form>