This module is based around a simple type alias over elm-verify's Validator type that I commonly find myself using.
Whereas the Validator
type is defined as
type alias Validator error input verified =
input -> Result ( error, List error ) verified
The FormValidator
types is defined
type alias FormValidator input verified =
input -> Result (form -> form) verified
Validator is great if you wish for the failure of validation to be a list of errors, but what if we have those errors expressed on our model?
type alias Form =
{ firstName : String
, firstNameError : Maybe String
, lastName : String
, lastNameError : Maybe String
}
type alias ValidatedForm =
{ firstName : NonemptyString
, lastName : NonemptyString
}
We don't need a unified "error" type. Our errors are just part of our model. Here's a quick example of how this looks in action:
import Verify.Form exposing (FieldValidator, FormValidator)
firstNameValidator : FieldValidator String Form NonemptyString
firstNameValidator input =
case String.Nonempty.fromString input of
Just firstName ->
Ok firstName
Nothing ->
Err (\form -> { form | firstNameError = Just "First name cannot be empty" })
lastNameValidator : FieldValidator String Form NonemptyString
lastNameValidator input =
case String.Nonempty.fromString input of
Just lastName ->
Ok lastName
Nothing ->
Err (\form -> { form | lastNameError = Just "Last name cannot be empty" })
formValidator : FormValidator Model ValidatedForm
formValidator =
Verify.Form.ok ValidatedForm
|> Verify.Form.verify .firstName firstNameValidator
|> Verify.Form.verify .lastName lastNameValidator
now on form submit we may handle things thusly
update : Msg -> Form -> ( Form, Cmd Msg )
update msg form =
case msg of
SubmitForm ->
case Verify.Form.run formValidator form of
Ok validatedForm ->
( form, submitForm validatedForm )
Err formWithErrors ->
( formWithErrors, Cmd.none )
You may still get the full utility of
elm-verify's helper modules
and Validator
type. To turn a Validator
into a FieldValidator
, you may use liftValidator
.
We only need to provide a function that states where on the form we should put a list of errors
if any occur.
import String.Verify
import Verify
import Verify.Form exposing (FieldValidator)
nameValidator : FieldValidator String { form | nameErrors : Maybe (List String) } String
nameValidator =
String.Verify.notBlank "Name cannot be empty"
|> Verify.compose (String.Verify.minLength 2 "Name must be at least 2 characters long")
|> Verify.compose (String.Verify.maxLength 50 "Name must be at most 50 characters long")
|> Verify.compose
(\input ->
if input == "Tony" then
Err ( "Tony is not a valid name", [] )
else
Ok input
)
|> Verify.Form.liftValidator (\errors form -> { form | nameErrors = Just errors })
Verify.Validator (form -> form) form verified
Simple type alias over Validator
that forgoes an error type in favor of an "Error setter" for the the input
type.
field -> Result (form -> form) verified
A type alias to represent a validator that is applied to a field on a form.
keep : (form -> field) -> FormValidator form (field -> finally) -> FormValidator form finally
Creates a FormValidator
that automatically passes for a given field. Useful if we don't want
to enforce validation on something, but still want to keep it in the pipeline. Similar to
Verify.keep
liftValidator : (( error, List error ) -> form -> form) -> Verify.Validator error input verified -> FieldValidator input form verified
Convenience function for using the Validator
type as a FieldValidator
. The first argument tells the resulting FormValidator
where on the form this FieldValidator
will
apply any errors to.
run : FormValidator form validatedForm -> form -> Result form validatedForm
Used to apply a FormValidator
to an input form.
validate : verified -> FormValidator input verified
Just a re-export of Verify.validate
for convenience.
verify : (form -> field) -> FieldValidator field form verified -> FormValidator form (verified -> finally) -> FormValidator form finally
Pipeline function that takes a field getter and a FieldValidator
to transform a FormValidator