You have to wrap every value of your form inside this type. For example, if your model looked something like
type alias FormerModel =
{ username : String
, email : String
, password : String
, passwordCopy : String
}
you have to change it to
type alias Model =
{ username : Validatable String String
, email : Validatable String String
, password : Validatable String String
, passwordCopy : Validatable String String
}
empty : Validatable a comparable
Use this to initialize your values:
init : Model
init =
{ username = empty
, email = empty
, pasword = empty
, passwordCopy = empty
}
unchecked : a -> Validatable a comparable
Use this to update a value in your model in reaction to user input:
update : Msg -> Model -> Model
update msg model =
case msg of
SetUsername string ->
{ model | username = unchecked string }
...
uncheck : Validatable a comparable -> Validatable a comparable
Set the value to unchecked if possible.
valid : a -> Validatable a comparable
Create a valid value. Usefull for initializing with a default value.
validValue : Validatable a comparable -> Maybe a
Return the actual value if it has been successfully validated at least once.
errors : Validatable a comparable -> Maybe (Set comparable)
Return all validation errors if the value has been tried to be validated at least once.
rawValue : Validatable a comparable -> Maybe a
I am not sure if it is a good idea to have this function at all, so it may be removed in the future.
Return the value, no matter if it is valid or not.
Note: If the value is in an invalid state, there may not be a raw value anymore.
Note: Don't use this to extract the value for submitting the form.
Use validValue
instead, to ensure at compile time that you only submit
valid values.
isNotEmpty : comparable -> Validatable String comparable -> Validatable String comparable
Check if the string value is non-empty. The first argument is the error which is recorded if the value is empty.
(unchecked "I am not empty!"
|> isNotEmpty "the value must not be empty"
|> validValue
)
== Just "I am not empty!"
(unchecked ""
|> isNotEmpty "the value must not be empty"
|> errors
|> Maybe.map toList
)
== Just [ "the value must not be empty" ]
atLeast : Basics.Int -> comparable -> Validatable String comparable -> Validatable String comparable
Check if the string value is at least the given count of characters long.
consistsOfLetters : comparable -> Validatable String comparable -> Validatable String comparable
Check if the string value only consists of letters.
isEmail : comparable -> Validatable String comparable -> Validatable String comparable
Check if the string value is a proper email address.
isInt : comparable -> String -> Validatable Basics.Int comparable
Try to cast a String
to an Int
.
isFloat : comparable -> String -> Validatable Basics.Float comparable
Try to cast a String
to a Float
.
try : (a -> Result err b) -> (err -> comparable) -> a -> Validatable b comparable
Run the provided computation which might result in an error. If it succeeds, we get a valid value, if it fails we get an invalid state with the given errors. So, you can do something like this:
("not a number"
|> try String.toInt (\err -> "You must provide an integer: " ++ err)
|> errors
|> Maybe.map toList
)
== Just [ "You must provide an integer: could not convert ..." ]
satisfies : (a -> Basics.Bool) -> comparable -> Validatable a comparable -> Validatable a comparable
Check if the value satisfies the condition. If not add the provided error to the list of errors.
Note: If the value was in an invalid state before and satisfies the condition we drop the previous errors and return a valid value.
equals : a -> comparable -> Validatable a comparable -> Validatable a comparable
Given a reference value, check if the value equals it.
addErrors : Set comparable -> Validatable a comparable -> Validatable a comparable
Add the given set of validation errors. This makes every value which is not empty invalid. You can use this function if you need to show validations to the user which can only be performed on the server, for example checking if a username is still available.
Note: If the set is empty, we do not change the state of the value.
map : (a -> b) -> Validatable a comparable -> Validatable b comparable
Apply the given function on the actual value.
mapErrors : (comparableA -> comparableB) -> Validatable a comparableA -> Validatable a comparableB
Apply the given function on the error values.
maybe : (Validatable a comparable -> Validatable a comparable) -> Validatable (Maybe a) comparable -> Validatable (Maybe a) comparable
Apply the validator on maybe values. If the value is Nothing
, it
is left unchanged. This is usefull if you need to validate optional
arguments, for example
nickname : Validatable (Maybe String) String
nickname =
valid Nothing
(nickname
|> maybe (consistsOfLetters "nickname must consist of letters only")
|> validValue
)
== Just Nothing
invalidNickname : Validatable (Maybe String) String
invalidNickname =
unchecked (Just "123")
(invalidNickname
|> maybe (consistsOfLetters "nickname must consist of letters only")
|> errors
|> Set.toList
)
== Just [ "nickname must consist of letters only" ]
with : Validatable a comparable -> (a -> Validatable b comparable -> Validatable b comparable) -> Validatable b comparable -> Validatable b comparable
Apply a validation only if another value was successfully validated. This unchecks the value if the provided value was not valid. For example, you can do something like this
password : Validatable String String
passwordCopy : Validatable String String
passwordCopy =
oldPasswordCopy
|> Validate.with password
(\validPassword ->
Validate.equals validPassword "Both passwords have to match up."
)