# What's Your Favorite Form Lib?

**URL:** <https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370>\
**Category:** Learn\
**Created:** [September 24, 2019, 7:26pm UTC](https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370 "2019-09-24T19:26:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![derrickbeining](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/derrickbeining/32/5078_2.png) [@derrickbeining](https://discourse.elm-lang.org/u/derrickbeining)\
**Post date:** [September 24, 2019, 7:26pm UTC](https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370/1 "2019-09-24T19:26:32Z")

</div>

What’s your favorite library for working with forms (and validating them) and why? Or is it more common to just roll-your-own solution? I’m looking at `etaque/elm-form` and `hecrj/composable-form` at the moment because they have the most GitHub stars among the libs I’ve seen, but I’m sure there are other good options. I don’t have time to vet a bunch of them personally, but would really like to have some confidence that I’m not going to regret my choice down the road.

To that end, would you mind sharing what your favorite form library is, and perhaps why? If someone has already mentioned your favorite, just ❤ their comment to keep things tidy.

---

<div class="post-metadata">

**Author:** ![Jayshua](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/jayshua/32/2707_2.png) [@Jayshua](https://discourse.elm-lang.org/u/Jayshua)\
**Post date:** [September 25, 2019, 4:14pm UTC](https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370/2 "2019-09-25T16:14:33Z")

</div>

In one of my applications I use a custom implementation of the idea described here: [https://arow.info/posts/2019/form-decoding/](https://arow.info/posts/2019/form-decoding/)

I like this strategy because it separates the form _definition_ (view code) from the form _validation_ which in my opinion should be two separate things. It also has the flexibility to show errors either next to the inputs or at the top of the form, or both. Whatever makes sense for the form. My custom implementation allows me to generate types from the validation/decoding that I can feed directly into the API generated by [elm-graphql](https://package.elm-lang.org/packages/dillonkearns/elm-graphql/latest/). This means I don’t have to write any additional code for converting the validated data into JSON or something else after the form decoder completes its validation.

So basically I use elm-graphql to select the data directly into the a record of string values (even if I want the user to provide a number - since that’s the appropriate data type for HTML input) then have a form decoder that decodes directly into the input records expected by the GraphQL API.

Additionally I write `Html.input [Evt.onInput (\newName -> { person | name = newName})] []` instead of `Html.input [Evt.onInput SetName] []` which results in an `Html Person` type instead of `Html Msg`. Then at the top of the form I use `Html.map SetPerson` to convert it to `Html Msg`. This lets me avoid 50+ lines of uninteresting case statements in the update method. I’ve found this works well as long as you keep the `Html Person` type very targeted. Don’t try composing nested records or nested lists unless it is absolutely necessary. I’ve found composing like that typically gives very overly complicated code.

Finally, I took the above ideas and built a custom Form module specific to my application. So my typical form code on most pages looks like:

```elm
viewForm : List FormError -> FormModel -> Html Msg
viewForm =
  Form.view SetPerson
    [ Form.label "First Name"
    , Form.text Focus.firstName
    , Form.errors [(FirstNameRequired, "First Name is Required")]
    , Form.label "Last Name"
    , Form.text Focus.lastName
    , Form.errors [(LastNameRequired, "Last Name is Required")]
    , Form.label "Age"
    , Form.text Focus.age
    , Form.errors [(AgeNotPositive, "Age Must be Positive"), (AgeNotNumeric, "Age Must be a Number")]
    ]

decodePerson : FormDecoder Api.InputObject.Person FormError
decodePerson =
  Form.succed Api.InputObject.Person
    |> Form.requiredString FirstNameRequired .firstName
    |> Form.requiredString LastNameRequired .lastName
    |> Form.positive AgeNotPositive (Form.requiredInt AgeNotNumeric .age)

```

---

<div class="post-metadata">

**Author:** ![Chadtech](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/chadtech/32/609_2.png) [@Chadtech](https://discourse.elm-lang.org/u/Chadtech)\
**Post date:** [September 30, 2019, 12:00pm UTC](https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370/3 "2019-09-30T12:00:29Z")

</div>

I am kind of in the “roll your own” camp.

I think its kind of hard to find a one-size-fits-all solution to forms.

A lot of similar and related things fall into the category of “forms”, so its hard to know exactly if any form package is addressing your particular form needs. There are a number of questions you have to ask yourself about what UX you want your project to have that will greatly change the answer to how your form should be coded. For example:

- Is your form purely a UI thing?
- Does “validation” for you, include constructing valid data `-> Result error data`, or just checking if data is valid `-> Bool`?
- What are you validating, specific fields or the entire form? Do the fields depend on each other?
- When do they validate? On blur? On interaction? When you click submit? Will different fields validate differently?
- Are the fields of your form dynamic?

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [October 10, 2019, 12:00pm UTC](https://discourse.elm-lang.org/t/whats-your-favorite-form-lib/4370/4 "2019-10-10T12:00:30Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
