Skip to content

surrsurus/phoenix_typed_form

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PhoenixTypedForm CI Hex.pm

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

Example

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

  1. create a new form and put it in your socket assigns
  2. 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} %>

Documentation

Read the docs on HexDocs: https://hexdocs.pm/phoenix_typed_form/PhoenixTypedForm.html

Installation

Add phoenix_typed_form to your list of dependencies in mix.exs:

def deps do
  [
    {:phoenix_typed_form, "~> 0.1.1"}
  ]
end