{"id":20971519,"url":"https://github.com/surrsurus/phoenix_typed_form","last_synced_at":"2026-02-08T14:33:46.490Z","repository":{"id":227323727,"uuid":"771124894","full_name":"surrsurus/phoenix_typed_form","owner":"surrsurus","description":"Enforce a typed schema for your Phoenix LiveView forms","archived":false,"fork":false,"pushed_at":"2025-01-13T17:43:22.000Z","size":58,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-29T02:08:06.555Z","etag":null,"topics":["elixir","elixir-lang","elixir-phoenix","form-validation","forms","phoenix","phoenix-framework","phoenix-liveview"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/phoenix_typed_form","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/surrsurus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-12T18:20:42.000Z","updated_at":"2024-07-09T15:01:31.000Z","dependencies_parsed_at":"2024-03-28T20:35:24.345Z","dependency_job_id":"42aab6c7-424e-4d42-88c8-841335b7eb75","html_url":"https://github.com/surrsurus/phoenix_typed_form","commit_stats":null,"previous_names":["surrsurus/phoenix_typed_form"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surrsurus%2Fphoenix_typed_form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surrsurus%2Fphoenix_typed_form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surrsurus%2Fphoenix_typed_form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/surrsurus%2Fphoenix_typed_form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/surrsurus","download_url":"https://codeload.github.com/surrsurus/phoenix_typed_form/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254131916,"owners_count":22020043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","elixir-lang","elixir-phoenix","form-validation","forms","phoenix","phoenix-framework","phoenix-liveview"],"created_at":"2024-11-19T04:03:29.791Z","updated_at":"2026-02-08T14:33:46.237Z","avatar_url":"https://github.com/surrsurus.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PhoenixTypedForm [![CI](https://github.com/surrsurus/phoenix_typed_form/actions/workflows/ci.yml/badge.svg)](https://github.com/surrsurus/phoenix_typed_form/actions/workflows/ci.yml) [![Hex.pm](https://img.shields.io/hexpm/v/phoenix_typed_form.svg)](https://hex.pm/packages/phoenix_typed_form)\n\nA macro that enforces a typed schema for your Phoenix LiveView forms.\nThe idea is that you define your schema and an optional changeset, then let the macro do the heavy lifting from there.\n\nThe 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.\n\nA typed form will have the following properties:\n- All form fields are required\n- All form fields are nillable - The user can delete a field and it should be fine to render, but not fine to submit\n- Is validate-able - All fields are required to be filled out before a form is considered valid\n\nThe macro suports:\n- Default values across all forms - Allows you to specify default form options via @default_values in the form of attrs.\n- Default values on new form creation - Allows you to override or specify a different default when creating a form - useful\n  for when your form requires something you don't have at compile time, like pulling in the policy quantity for a claim.\n- Custom changesets \u0026 Runtime changeset contraints - Allows you to specify constraints on the form at runtime,\n  like a max_qty for a claim form\n\n# Example\n\nHere'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\nenter a quantity for a purchase order. You'd define a module like this for your form:\n\n```elixir\ndefmodule BasicForm do\n  use PhoenixTypedForm\n\n  # Define the schema for the form\n  typed_schema do\n    field :qty, :integer\n  end\n\n  # Bring in the form helpers\n  def_typed_form()\n\n  # And finally render the form to the user\n  def render_form(assigns) do\n    # Some things to note:\n    # 1) phx-submit also works instead of phx-change\n    # 2) `value={@form.data.qty}` - This will show the last value that's been validated by the changeset\n    #     You can also use `value={@form.params.qty}` to show the last value that's been submitted instead\n    ~H\"\"\"\n    \u003c.form for={@form} phx-change=\"update-form\"\u003e\n      \u003cp\u003eEnter qty\u003c/p\u003e\n      \u003c.input\n        field={@form[:qty]}\n        type=\"number\"\n        step=\"1.0\"\n        label=\"Qty\"\n        min=\"0\"\n        value={@form.data.qty}\n        class={@class}\n        errors={get_error(@form, :qty)}\n        required\n      /\u003e\n    \u003c/.form\u003e\n    \"\"\"\n  end\nend\n```\n\nAnd then in your LiveView, all you have to do is\n1) create a new form and put it in your socket assigns\n2) handle the event fired by the form\n\nIf the new details are invalid, the form can render the changeset error straight to the user, giving them feedback as early as possible.\nThis macro could also be applied to forms in a controller, but it was intended to be used with LiveView.\n\n```elixir\ndefmodule YourLiveView do\n  use Phoenix.LiveView\n\n  def mount(_params, _session, socket) do\n    {:ok, assign(socket, form: BasicForm.new_form())}\n  end\n\n  def handle_event(\"update-form\", %{\"form\" =\u003e form_params}, socket) do\n    {:noreply, assign(socket, form: BasicForm.update_form(form_params))}\n  end\nend\n```\n\nTo add a form in your heex template, it's really simple. Just invoke the render_form function component:\n\n```elixir\n\u003c%= BasicForm.render_form form={@form} %\u003e\n```\n\n## Documentation\n\nRead the docs on HexDocs: https://hexdocs.pm/phoenix_typed_form/PhoenixTypedForm.html\n\n## Installation\n\nAdd `phoenix_typed_form` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:phoenix_typed_form, \"~\u003e 0.1.1\"}\n  ]\nend\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurrsurus%2Fphoenix_typed_form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsurrsurus%2Fphoenix_typed_form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsurrsurus%2Fphoenix_typed_form/lists"}