This library helps with building custom validators of a user input.
Many validators can be chained to perform validation of a single value.
Provides interface for combining validatiors of multiple input fields with (|>) operator.
Allows combination of required and optional fields.
Build a custom validator.
intValidator : Validator String InputError Int
intValidator =
Validator.custom (String.toInt >> Result.fromMaybe [ NaN ])Run validator.
intValidator : Validator String String Int
intValidator =
Validator.custom (String.toInt >> Result.fromMaybe [ "Not a number" ])
Validator.run intValidator "42"
--> (Ok 42)
Validator.run intValidator "Fat fingers"
--> (Err [ "Not a number" ])Create validator that always succeed.
Validator.run (Validator.succeed 3) "blah" --> (Ok 3)Create validator that always fails.
Validator.run (Validator.fail "Invalid") 123 --> (Err [ "Invalid" ])Transform validated value with a given function.
Validator.run (Validator.map ((+) 1) (Validator.succeed 2)) Nothing
--> (Ok 3)Apply a function if both arguments passed validation.
Validator.map2 (\x y -> x + y)
(Validator.succeed 1)
(Validator.succeed 2)
|> (\validator -> Validator.run validator ())
--> (Ok 3)Apply wrapped function to another wrapped value.
intValidator : Validator String String Int
intValidator =
Validator.custom (String.toInt >> Result.fromMaybe [ "Not a number" ])
Validator.run (Validator.succeed ((+) 2) |> Validator.andMap intValidator) "3"
--> (Ok 5)Chain together many validators.
intValidator
|> Validator.andThen
(\x ->
if x < 0 then
Validator.fail "Must be a positive number"
else
Validator.succeed x
)
-- ...Combine validators with required field.
type alias User =
{ name : String
, age : Int
, email : Email
}
type Email = Email String
parseEmail : String -> Result String Email
parseEmail str =
if String.contains "@" str then
Ok (Email str)
else
Err "Invalid email"
emailValidator : Validator String String Email
emailValidator =
Validator.custom (parseEmail >> Result.mapError List.singleton)
intValidator : Validator String String Int
intValidator =
Validator.custom (String.toInt >> Result.fromMaybe [ "Not a number" ])
type alias FormValues r =
{ r
| name : String
, age : String
, email : String
}
userValidator : Validator (FormValues r) String User
userValidator =
Validator.succeed User
|> Validator.required .name String.isEmpty "Name is required" (Validator.custom Ok)
|> Validator.required .age String.isEmpty "Age is required" intValidator
|> Validator.required .email String.isEmpty "Email is required" emailValidator
Validator.run userValidator { name = "John Doe", age = "", email = "test" }
--> Err [ "Age is required", "Invalid email" ]Combine validators with optional field.
type alias User =
{ name : String
, age : Int
, email : Email
}
type Email = Email String
parseEmail : String -> Result String Email
parseEmail str =
if String.contains "@" str then
Ok (Email str)
else
Err "Invalid email"
emailValidator : Validator String String Email
emailValidator =
Validator.custom (parseEmail >> Result.mapError List.singleton)
intValidator : Validator String String Int
intValidator =
Validator.custom (String.toInt >> Result.fromMaybe [ "Not a number" ])
type alias FormValues r =
{ r
| name : String
, age : String
, email : String
}
userValidator : Validator (FormValues r) String User
userValidator =
Validator.succeed User
|> Validator.required .name String.isEmpty "Name is required" (Validator.custom Ok)
|> Validator.optional .age String.isEmpty 10 intValidator
|> Validator.required .email String.isEmpty "Email is required" emailValidator
Validator.run userValidator { name = "John Doe", age = "", email = "happy@path" }
--> Ok (User "John Doe" 10 (Email "happy@path"))
Represents a validator of the input value. Validation can fail with a list of custom error messages.