dataval/form
Compose a form from multiple fields.
A form is a function that takes a raw dictionary of strings and returns either a successfully built value or a map of field errors.
Example
import dataval/field
import dataval/form
import dataval/parser
import dataval/validator
import gleam/dict
pub type CreateUser {
CreateUser(age: Int, name: String)
}
fn age_field() {
field.new("age")
|> field.with_parser(parser.int)
|> field.add_validator(validator.int_min(18))
}
fn name_field() {
field.new("name")
|> field.add_validator(validator.str_min(2))
}
pub fn create_user_form() {
use age <- form.field(age_field())
use name <- form.field(name_field())
form.create(CreateUser(age:, name:))
}
pub fn main() {
let user_form = create_user_form()
assert Ok(CreateUser(20, "Toto"))
== form.validate(user_form, [#("age", "20"), #("name", "Toto")])
assert Error(
dict.from_list([
#("age", [field.IntTooSmall(18)]),
#("name", [field.StringLengthTooShort(2)]),
]),
)
== form.validate(user_form, [#("age", "16"), #("name", "a")])
}
Details
Each form.field looks up the field name in the raw input, runs its
validators and parser, and passes the parsed value to the continuation.
Missing fields are treated as empty strings. If any field has errors,
validate returns Error with a dictionary of field names to errors.
Types
pub type FormState(a, custom) {
FormState(
value: a,
errors: dict.Dict(String, List(field.FieldError(custom))),
)
}
Constructors
-
FormState( value: a, errors: dict.Dict(String, List(field.FieldError(custom))), )
Values
pub fn field(
form_field: field.Field(a, custom),
continuation: fn(a) -> fn(dict.Dict(String, String)) -> FormState(
b,
custom,
),
) -> fn(dict.Dict(String, String)) -> FormState(b, custom)
Attach a field to the form. Missing fields in the raw input are treated as empty strings.