dillonkearns / elm-form / Form.Validation

Validations


type alias Field error parsed kind =
Validation error parsed kind { field : kind }

Represents a form field. This value is used for two purposes:

You get a Field from the pipeline of fields defined using Form.field and Form.hiddenField. The only other way to get a Field is to use global. You can use this special Field to attach validation errors to the form as a whole rather than to a specific field.

This type is one of the key designs in this package. Because we can share this Field type between the view and the parsing, we don't need to use "stringly typed" values to refer to fields in our form in an error-prone way. Instead, we know that a Field represents a form field that we have defined for the given Form. It's a little confusing that this Field type serves two purposes, but it allows us to have a safe way to reference a Form's fields, and doesn't require two declarations with a duplicate parameter list.

See the Form docs for more on how to use Fields to render your Form's view and define its combine Validation.


type alias Validation error parsed kind constraints =
Pages.Internal.Form.Validation error parsed kind constraints

A Validation represents a parsed value or a list of errors.

succeed : parsed -> Validation error parsed kind constraints

Get a Combined value that successfully parses into the given value with no errors.

Helpful for starting a chain of Validation functions that will eventually parse into a value. See andMap for an example of a common idiom.

andMap : Validation error a named1 constraints1 -> Validation error (a -> b) named2 constraints2 -> Validation error b Basics.Never constraints3

Lets you combine Validation's in a pipeline.

import Form
import Form.Field as Field
import Form.Validation as Validation

example =
    (\first middle last ->
        { combine =
            Validation.succeed
                (\vFirst vMiddle vLast ->
                    vFirst ++ " " ++ vMiddle ++ " " ++ vLast
                )
                |> Validation.andMap first
                |> Validation.andMap middle
                |> Validation.andMap last
        , view = \_ -> []
        }
    )
        |> Form.form
        |> Form.field "first" (Field.text |> Field.required "Required")
        |> Form.field "middle" (Field.text |> Field.required "Required")
        |> Form.field "last" (Field.text |> Field.required "Required")

andThen : (parsed -> Validation error mapped named1 constraints1) -> Validation error parsed named2 constraints2 -> Validation error mapped Basics.Never constraintsAny

Continue a Validation based on the given parsed value.

import Date
import Form
import Form.Field as Field
import Form.Validation as Validation

example : Form.HtmlForm String { date : Date, nights : Int } input msg
example =
    (\checkIn checkOut ->
        { combine =
            Validation.map2
                (\checkinValue checkoutValue ->
                    Validation.succeed
                        { date = checkinValue
                        , nights = Date.toRataDie checkoutValue - Date.toRataDie checkinValue
                        }
                        |> Validation.withErrorIf (Date.toRataDie checkinValue >= Date.toRataDie checkoutValue) checkIn "Must be before checkout"
                )
                checkIn
                checkOut
                |> Validation.andThen identity
        , view = \_ -> []
        }
    )
        |> Form.form
        |> Form.field "checkin"
            (Field.date
                { invalid = \_ -> "Invalid" }
                |> Field.required "Required"
            )
        |> Form.field "checkout"
            (Field.date
                { invalid = \_ -> "Invalid" }
                |> Field.required "Required"
            )

fail : error -> Field error parsed1 field -> Validation error parsed kind constraints

Add an error to the given Field, short-circuiting its parsed value so that it will fail to parse. This can be helpful if you want to fail with a value that you can combine together with other values because it has an unbound parsed type variable. Similar to how Json.Decode.fail gives you a Decoder a.

See withError if you want to add an error without short-circuiting the parsed value.

fromResult : Field error (Result error parsed) kind -> Validation error parsed Basics.Never Basics.Never

Resolve a Result within a Field. If it is Err, the error will be added to the Field's errors.

map : (parsed -> mapped) -> Validation error parsed named constraint -> Validation error mapped erasedKind erasedConstraints

Apply a function to the parsed value.

import Form.Validation as Validation

type Uuid
    = Uuid String

example =
    (\uuid ->
        { combine =
            Validation.succeed identity
                |> Validation.andMap (uuid |> Validation.map Uuid)
        , view = \_ -> []
        }
    )
        |> Form.form
        |> Form.hiddenField "uuid" (Field.text |> Field.required "Required")

map2 : (a -> b -> c) -> Validation error a named1 constraints1 -> Validation error b named2 constraints2 -> Validation error c Basics.Never constraintsAny

Combine together two Validation's.

import Form
import Form.Field as Field
import Form.Validation as Validation

example =
    (\first last ->
        { combine =
            Validation.map2 Tuple.pair
                first
                last
        , view = \_ -> [{- ... -}]
        }
    )
        |> Form.form
        |> Form.field "first" (Field.text |> Field.required "Required")
        |> Form.field "last" (Field.text |> Field.required "Required")

withError : Field error parsed1 field -> error -> Validation error parsed2 named constraints -> Validation error parsed2 named constraints

Add an error to the given Field.

withErrorIf : Basics.Bool -> Field error ignored field -> error -> Validation error parsed named constraints -> Validation error parsed named constraints

Conditionally add an error to the given Field.

import Date
import Form.Validation as Validation

example checkIn checkOut =
    Validation.map2
        (\checkinValue checkoutValue ->
            Validation.succeed
                { date = checkinValue
                , nights = Date.toRataDie checkoutValue - Date.toRataDie checkinValue
                }
                |> Validation.withErrorIf (Date.toRataDie checkinValue >= Date.toRataDie checkoutValue) checkIn "Must be before checkout"
        )
        checkIn
        checkOut
        |> Validation.andThen identity

withFallback : parsed -> Validation error parsed named constraints -> Validation error parsed named constraints

Include a fallback value to parse into. Does not remove any previous validation errors that have been encountered so it will not effect whether it parses to Valid or Invalid.

Field Metadata

value : Validation error parsed named constraint -> Maybe parsed

Get the parsed value if it is parseable (could be either invalid or valid).

fieldName : Field error parsed kind -> String

Get the Field's name.


type FieldStatus
    = NotVisited
    | Focused
    | Changed
    | Blurred

elm-form manages the state of a form's fields, including FieldStatus.

FieldStatus goes through the following states in this order, and never goes backwards (unless it is changed manually through the Form.Model value):

  1. NotVisited - The initial FieldStatus for all fields. The field hasn't been changed or focused.
  2. Focused - The field has been focused, but not changed or blurred.
  3. Changed - The field has had an input event, but has not yet been blurred (lost focus).
  4. Blurred - The field has been blurred (lost focus).

You can use a Form's submitAttempted state and/or a Field's FieldStatus to decide when to render a Field's validation errors.

For example, you might choose to render a Field's validation errors once Field has been Blurred so that the user doesn't see validation errors before they've had a chance to input a valid value (it can be an annoying user experience to get error feedback too early).

See Form.errorsForField for a common way to use a Field's FieldStatus.

fieldStatus : Field error parsed kind -> FieldStatus

Get the Field's FieldStatus.

fieldStatusToString : FieldStatus -> String

Mostly useful for debugging, you'll usually want to compare FieldStatus to other FieldStatus values or use helpers like statusAtLeast.

statusAtLeast : FieldStatus -> Field error parsed kind -> Basics.Bool

elm-form manages form fields' FieldStatus in the order described in FieldStatus.

This function is useful when writing a condition for when to show a Field's validation errors in the view. See Form.errorsForField for an example.

Mapping

map3 : (a1 -> a2 -> a3 -> a4) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 Basics.Never constraintsAny

map4 : (a1 -> a2 -> a3 -> a4 -> a5) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 Basics.Never constraintsAny

map5 : (a1 -> a2 -> a3 -> a4 -> a5 -> a6) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 named5 constraints5 -> Validation error a6 Basics.Never constraintsAny

map6 : (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 named5 constraints5 -> Validation error a6 named6 constraints6 -> Validation error a7 Basics.Never constraintsAny

map7 : (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 named5 constraints5 -> Validation error a6 named6 constraints6 -> Validation error a7 named7 constraints7 -> Validation error a8 Basics.Never constraintsAny

map8 : (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 named5 constraints5 -> Validation error a6 named6 constraints6 -> Validation error a7 named7 constraints7 -> Validation error a8 named8 constraints8 -> Validation error a9 Basics.Never constraintsAny

map9 : (a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7 -> a8 -> a9 -> a10) -> Validation error a1 named1 constraints1 -> Validation error a2 named2 constraints2 -> Validation error a3 named3 constraints3 -> Validation error a4 named4 constraints4 -> Validation error a5 named5 constraints5 -> Validation error a6 named6 constraints6 -> Validation error a7 named7 constraints7 -> Validation error a8 named8 constraints8 -> Validation error a9 named9 constraints9 -> Validation error a10 Basics.Never constraintsAny

Global Validation

global : Field error () Basics.Never

A Field that represents the form as a whole. This is useful for attaching validation errors to the form as a whole rather than to a specific field.