A macro that enforces a typed schema for your Phoenix LiveView forms. The idea is that you define your schema and an optional changeset, then let the macro do the heavy lifting from there.
The macro provides a way to create a new form, update a form, and check if a form is valid for submission, all based on your schema and changeset.
A typed form will have the following properties:
- All form fields are required
- All form fields are nillable - The user can delete a field and it should be fine to render, but not fine to submit
- Is validate-able - All fields are required to be filled out before a form is considered valid
The macro suports:
- Default values across all forms - Allows you to specify default form options via @default_values in the form of attrs.
- Default values on new form creation - Allows you to override or specify a different default when creating a form - useful for when your form requires something you don't have at compile time, like pulling in the policy quantity for a claim.
- Custom changesets & Runtime changeset contraints - Allows you to specify constraints on the form at runtime, like a max_qty for a claim form
Here's an example of how to use this module in your Phoenix app. Let's say you want a really simple form for a user to enter a quantity for a purchase order. You'd define a module like this for your form:
defmodule BasicForm do
use PhoenixTypedForm
# Define the schema for the form
typed_schema do
field :qty, :integer
end
# Bring in the form helpers
def_typed_form()
# And finally render the form to the user
def render_form(assigns) do
# Some things to note:
# 1) phx-submit also works instead of phx-change
# 2) `value={@form.data.qty}` - This will show the last value that's been validated by the changeset
# You can also use `value={@form.params.qty}` to show the last value that's been submitted instead
~H"""
<.form for={@form} phx-change="update-form">
<p>Enter qty</p>
<.input
field={@form[:qty]}
type="number"
step="1.0"
label="Qty"
min="0"
value={@form.data.qty}
class={@class}
errors={get_error(@form, :qty)}
required
/>
</.form>
"""
end
end
And then in your LiveView, all you have to do is
- create a new form and put it in your socket assigns
- handle the event fired by the form
If the new details are invalid, the form can render the changeset error straight to the user, giving them feedback as early as possible. This macro could also be applied to forms in a controller, but it was intended to be used with LiveView.
defmodule YourLiveView do
use Phoenix.LiveView
def mount(_params, _session, socket) do
{:ok, assign(socket, form: BasicForm.new_form())}
end
def handle_event("update-form", %{"form" => form_params}, socket) do
{:noreply, assign(socket, form: BasicForm.update_form(form_params))}
end
end
To add a form in your heex template, it's really simple. Just invoke the render_form function component:
<%= BasicForm.render_form form={@form} %>
Read the docs on HexDocs: https://hexdocs.pm/phoenix_typed_form/PhoenixTypedForm.html
Add phoenix_typed_form
to your list of dependencies in mix.exs
:
def deps do
[
{:phoenix_typed_form, "~> 0.1.1"}
]
end