package dream-html

  1. Overview
  2. Docs

Typed, extensible HTML form decoder with error reporting for all form field validation failures.

See the bottom of the page for complete examples.

  • since 3.7.0.

Basic type decoders

type 'a ty = string -> ('a, string) Stdlib.result

The type of a decoder for a single form field value of type 'a which can successfully decode the field value or fail with an error message key.

val bool : bool ty
val char : char ty
val float : float ty
val int : int ty
val int32 : int32 ty
val int64 : int64 ty
val string : string ty

Forms and fields

type 'a t

The type of a form (a form field by itself is also considered a form) which can decode values of type 'a or fail with a list of error message keys.

val list : 'a ty -> string -> 'a list t

list ty name is a form field which can decode a list of values which can each be decoded by ty.

val optional : 'a ty -> string -> 'a option t

optional ty name is a form field which can decode an optional value from the form.

val required : 'a ty -> string -> 'a t

required ty name is a form field which can decode a required value from the form. If at least one value corresponding to the given name does not appear in the form, the decoding fails with an error.

val ensure : string -> ('b -> bool) -> ('a ty -> string -> 'b t) -> 'a ty -> string -> 'b t

ensure message condition field ty name is a form field which imposes an additional condition on top of the existing field. If the condition fails, the result is an error message. It is suggested that the message be a translation key so that the application can be localized to different languages.

Form decoders

val let+ : 'a t -> ('a -> 'b) -> 'b t

let+ email = required string "email" decodes a form field named email as a string.

val and+ : 'a t -> 'b t -> ('a * 'b) t

and+ password = required string "password" continues decoding in an existing form declaration and decodes a form field password as a string.

val or : 'a t -> 'a t -> 'a t

form1 or form2 is form1 if it succeeds, else form2.

val validate : 'a t -> (string * string) list -> ('a, (string * string) list) Stdlib.result

validate form values is a result of validating the given form's values. It may be either some value of type 'a or a list of form field names and the corresponding error message keys.

val pp_error : (string * string) list Fmt.t

pp_error is a helper pretty-printer for debugging/troubleshooting form validation errors.

Error keys

When errors are reported, the following keys are used instead of English strings. These keys can be used for localizing the error messages. The suggested default English translations are given below.

These keys are modelled after Play Framework.

val error_expected_bool : string

Please enter true or false.

val error_expected_char : string

Please enter a single character.

val error_expected_single : string

Please enter a single value.

val error_expected_int : string

Please enter a valid integer.

val error_expected_int32 : string

Please enter a valid 32-bit integer.

val error_expected_int64 : string

Please enter a valid 64-bit integer.

val error_expected_number : string

Please enter a valid number.

val error_required : string

Please enter a value.

Examples

Basic complete example:

type user = { name : string; age : int option}

open Dream_html.Form

let user_form =
  let+ name = required string "name"
  and+ age = optional int "age" in
  { name; age }

let dream_form = ["age", "42"; "name", "Bob"]
let user_result = validate user_form dream_form

Result: Ok { name = "Bob"; age = Some 42 }

Sad path:

validate user_form ["age", "none"]

Result: Error [("age", "error.expected.int"); ("name", "error.required")]

Notice that validation errors for all fields are reported. This is a critical design decision that differentiates this module from others available in OCaml.

Decode list of values from form:

type plan = { id : string; features : string list }

let plan_form =
  let+ id = required string "id"
  and+ features = list string "features" in
  { id; features }

validate plan_form ["id", "foo"]

Result: Ok {id = "foo"; features = []}

validate plan_form ["id", "foo"; "features", "f1"; "features", "f2"]

Result: Ok {id = "foo"; features = ["f1"; "f2"]}

Note that the names can be anything, eg "features[]" if you prefer.

Add further requirements to field values:

let plan_form =
  let+ id = ensure "error.expected.nonempty" (( <> ) "") required string "id"
  and+ features = list string "features" in
  { id; features }

validate plan_form ["id", ""]

Result: Error [("id", "error.expected.nonempty")]

OCaml

Innovation. Community. Security.