Skip to content

Instantly share code, notes, and snippets.

@adinapoli
Last active February 5, 2017 18:13
Show Gist options
  • Save adinapoli/bc9cb5bc1c9ade55771a315f5d535cc4 to your computer and use it in GitHub Desktop.
Save adinapoli/bc9cb5bc1c9ade55771a315f5d535cc4 to your computer and use it in GitHub Desktop.
How to do live form validation in Elm?

The context: I'm trying to write a small widget where the user can dynamically add and remove parcels, for a shipment e-commerce website. Example:

screen shot 2017-02-05 at 18 58 11

I would like to present user with live form validation: the idea would be to display a message if, for example, the user inserted a non-int value (those fields translate as: weight, width, length, depth).

Suppose I have the following (simplified) model:

type alias LocalID =
    Int

type Envelope
    = Envelope EnvelopeWeight

type alias Weight = Int
type alias Width  = Int
type alias Height = Int
type alias Depth  = Int

type Parcel
    = Parcel Weight Width Height Depth
    
type ParcelAsTxt = ParcelAsTxt String String String String

type Good
    = ENV Envelope
    | PAR Parcel

I'm giving elm-validate a go, and my idea would be to feed a Validator a fully fledged Parcel, so that the validation could be written like this:

validateParcel : Parcel -> List String
validateParcel =
    Validate.all
        [ .weight  >> ifNotInt "Please insert an int"
        ... -- you get the idea
        ]

But here I have a problem; I want to bind a particular event to those 4 input fields, so that every time one of those 4 changes, I can somehow read back the values of those 4 dom elements, assemble a Parcel out of it, and feed it into my validator.

To be even more explicit, this is how a piece of my view looks like:

viewParcel : Parcel -> Html Msg
viewParcel p =
    Html.form [ ]
        [ div [ ]
            [ div [ ] [ input [ on "input change" ???, type_ "text", placeholder "Peso" ] [] ]
            , div [  ] [ input [ type_ "text", placeholder "Lunghezza" ] [] ]
            , div [ ] [ input [ type_ "text", placeholder "Altezza" ] [] ]
            , div [ ] [ input [ type_ "text", placeholder "Profondita'" ] [] ]
            ]
        ]

??? here is the placeholder of the Decoder I'm trying I guess to write to solve this particular problem. Ideally that would get all the 4 fields and produce a Msg to validate a particular Parcel

In the jQuery world, I would simply bind those inputs fields to an on "change input" event, would get the value out of those 4 fields with $(myDomEl).val(), assemble my model and run whatever function I needed to.

Thus, my question is: What's the most idomatic way to do this in Elm?

Thanks everyone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment