A library for building dynamic webapps, using Js_of_ocaml
Module type
Class type
Library bonsai.web_ui_form
module View : sig ... end

Bonsai-web-forms has its own view type so that it can build a more structured view of the form. You can convert it to a Vdom node with the to_vdom* functions.

type 'a t
val return : 'a -> 'a t

return produces a bonsai form that will always produce the same value. set and normalize will do nothing to the form provided by this.

val return_error : Core.Error.t -> _ t

return_error produces a form that always fails validation.

val map_error : 'a t -> f:( Core.Error.t -> Core.Error.t ) -> 'a t
val value : 'a t -> 'a Core.Or_error.t
val value_or_default : 'a t -> default:'a -> 'a
val is_valid : _ t -> bool

is_valid returns true if value would return Ok.

val view : _ t -> View.t
module Submit : sig ... end
val view_as_vdom : ?on_submit:'a Submit.t -> ?editable:[ `Yes_always | `Currently_yes | `Currently_no ] -> 'a t -> Bonsai_web.Vdom.Node.t

view_as_vdom produces the vdom representation of the form.

editable defaults to `Yes_always, which should be used when form input can't be disabled. `Currently_yes allows editing, but generates less diff when toggled with `Currently_no. When editable is `Currently_no, the view is wrapped in a fieldset that disables all of the inputs in the form.

Regardless of the value of editable, scheduling the Form.set effect will still change the values in the form.

Known bugs: While setting editable to `Currently_no prevents modification of most browser-builtin input elements, some custom form elements like the drag-and-drop, multiselect, and removing items using the pills in typeahead-multi for don't currently respect this and can be modified anyway. Work is underway to fix these.

val set : 'a t -> 'a -> unit Ui_effect.t

set fills the form with the provided value, setting the contents of form-elements if possible

val normalize : _ t -> unit Ui_effect.t

normalize sets the contents of a form to its current value. This only impacts values that have a "normalized" form. For example, a float-producing textbox being normalized might go from displaying "1.000" to "1."

val both : 'a t -> 'b t -> ('a * 'b) t

Combines two forms into another one that produces both values from the inputs in tupled form.

val project : 'a t -> parse_exn:( 'a -> 'b ) -> unparse:( 'b -> 'a ) -> 'b t

project is the powerhouse of the library; Using this function, you can change the type produced. Think of it like map.

  • parse_exn is a function that converts "forwards". As its name implies, you're free (and encouraged to) throw exceptions when the type conversion would fail.
  • unparse goes in the opposite direction. This one must not throw.


let _ : int Form.t =
    (a: string Form.t)
val project' : 'a t -> parse:( 'a -> 'b Core.Or_error.t ) -> unparse:( 'b -> 'a ) -> 'b t

The same as project except that the parse function is Or_error returning.

val validate : 'a t -> f:( 'a -> unit Core.Or_error.t ) -> 'a t

validate can provide additional validation of a value, but unlike project or project', it doesn't change the type of the resulting form

val label : string -> 'a t -> 'a t

Adds a label to the form.

val label' : Bonsai_web.Vdom.Node.t -> 'a t -> 'a t

Same as label, but it lets you use an arbitrary vdom node instead of just a string.

val tooltip : string -> 'a t -> 'a t

Adds a tooltip to the form.

val tooltip' : Bonsai_web.Vdom.Node.t -> 'a t -> 'a t

Same as tooltip, but it lets you use an arbitrary vdom node instead of just a string.

val group : string -> 'a t -> 'a t

Sometimes it's nice to collect a bunch of forms under a label. Because 'a t can represent multiple rows of forms, the group and group' functions put those rows underneath a header.Record_builder

        sub1 _________
        sub2 _________
val group' : Bonsai_web.Vdom.Node.t -> 'a t -> 'a t

Same as group, but it lets you use an arbitrary vdom node instead of just a string.

val optional : 'a t -> is_some:( 'a -> bool ) -> none:'a -> 'a option t

optional takes a 'a t and produces a 'a option t when given a "some detector" and a token "none" value. is_some none must be false.


let _ : string option t =
    (a: string t)
    ~is_some:(Fn.non String.is_empty)
val optional' : 'a t -> parse:( 'a -> 'b option Core.Or_error.t ) -> unparse:( 'b -> 'a ) -> none:'a -> 'b option t

An alternative "optional form" construction function; optional' gives you the ability to produce the full set of parse options:

  • Ok (Some b)
  • Ok None
  • Error error] while also converting to another type ('a -> 'b option) at the same time.
module Record_builder_lib := Record_builder

Record_builder is the primary way to compose form values using this library.

module Dynamic : sig ... end

Unlike the rest of the API which operates on values of type Form.t value values, they operate on Form.t Value.t, and typically return Computation.t.

module Expert : sig ... end
module Private : sig ... end
module Elements : sig ... end
module Typed : sig ... end

The functions in this module can be hard to understand Please look at the examples in lib/bonsai/examples/forms/