On this page:
form+  submit
form
required-unless
at-least
number-in-range
list-longer-than
checkbox
input-date
input-datetime
input-email
input-file
input-number
input-range
input-text
input-time
textarea
radios
select
checkboxes
make-autofill
make-autofill-meta

6.1.3 Form0🔗

 (require conscript/form0) package: conscript

This module reprovides nearly all the bindings in the forms library for creating forms in your study pages, as well as some additional conveniences for using that library.

See the Forms Recipe for steps and examples to combine these procedures into working forms in your study steps.

In addition to the tutorials in this documentation, see (part ("(lib forms/forms.scrbl)" "top")) for a tutorial that walks through the functionality of Forms.

syntax

(form+submit [id formlet-expr] ...)

Returns two values: a form value and a procedure that is called when the form is submitted.

Each id should be a variable declared with defvar or similar, and each formlet-expr should be one of the values in (part ("(lib forms/forms.scrbl)" "formlets")), or an ensure expression combining one of those formlets with one or more (part ("(lib forms/forms.scrbl)" "validators")).

Examples:
> (defvar my-name)
> (defvar my-middle-name)
> (defvar my-age)
> (define-values (form-data on-submit)
    (form+submit
      [my-name (ensure binding/text (required))]
      [my-middle-name binding/text]
      [my-age (ensure binding/number (required))]))

procedure

(form f    
  action    
  render    
  [#:id id    
  #:enctype enctype    
  #:combine combine-proc    
  #:defaults defaults])  xexpr?
  f : form?
  action : (-> void?)
  render : (-> (widget-renderer/c) xexpr?)
  id : string? = ""
  enctype : string? = "multipart/form-data"
  combine-proc : (-> any/c any/c any/c any/c)
   = 
(λ (k v1 v2)
  (if (pair? v1)
      (append v1 (list v2))
      (list v1 v2)))
  defaults : hash? = (hash)
Renders the form represented by f (created using form+submit or form*) using render and executes action on successful submission, then continues to the next step in the study.

Identical to the form from congame/components/study except for the default combine-proc: when there are multiple bindings for the same field, this procedure’s default combine-proc combines all the bindings for that field into a list (as described in the documentation for form-run).

procedure

(required-unless pred)  
(-> (or/c string? #f)
    (or/c (cons/c 'ok any/c)
          (cons/c 'err string?)))
  pred : (-> any/c)
Similar to required, produces a validator procedure that ensures a value is present (i.e. not #f), except that if pred produces a non-false value at validation time, then the value is allowed to be absent. Use inside ensure when building forms.

procedure

(at-least n)  
(-> (or/c number? #f)
    (or/c (cons/c 'ok any/c)
          (cons/c 'err string?)))
  n : number?
Produces a validator procedure that ensures a numeric value is greater than or equal to n. If the value is #f (indicating an empty field), validation passes. Use inside ensure when building forms with numeric inputs.

Examples:
> (defvar contribution)
> (define-values (form-data on-submit)
    (form+submit
      [contribution (ensure binding/number (at-least 0))]))

procedure

(number-in-range lo hi)  
(-> (or/c number? #f)
    (or/c (cons/c 'ok any/c)
          (cons/c 'err string?)))
  lo : number?
  hi : number?
Produces a validator procedure that ensures a numeric value falls within the range [lo, hi] (inclusive). If the value is #f (indicating an empty field), validation passes. Use inside ensure when building forms with numeric inputs that must stay within a specific range.

Examples:
> (defvar rating)
> (define-values (form-data on-submit)
    (form+submit
      [rating (ensure binding/number (number-in-range 1 10))]))

procedure

(list-longer-than n)  
(-> any/c
    (or/c (cons/c 'ok any/c)
          (cons/c 'err string?)))
  n : exact-nonnegative-integer?
Produces a validator procedure that ensures a value is a non-empty list containing at least n items. Unlike at-least and number-in-range, this validator requires the value to be present and will fail if the value is #f or not a list. Use inside ensure with binding/list when building forms that collect multiple values from inputs sharing the same field name (such as multiple checkboxes or number inputs).

Examples:
> (defvar ratings)
> (define-values (form-data on-submit)
    (form+submit
      [ratings (ensure binding/list (list-longer-than 3))]))

procedure

(checkbox [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-date [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-datetime [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-email [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-file label)  widget/c

  label : (or/c string? #f)

procedure

(input-number [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-range [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-text [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(input-time [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null

procedure

(textarea [label] #:attributes attrs)  widget/c

  label : (or/c string? #f) = #f
  attrs : null
Returns a widget that can render the given input type.

Note: input-file creates a file upload widget and does not accept the #:attributes parameter.

Examples:
> ((checkbox) "agree" #f null)

'(div

  ((class "field-group"))

  (label () "Agree" (input ((type "checkbox") (name "agree")))))

> ((input-time) "arrived" #f null)

'(div

  ((class "field-group"))

  (label () "Arrived" (input ((type "time") (name "arrived")))))

procedure

(radios options [label] #:attributes attrs)  widget/c

  options : radio-options/c
  label : (or/c string? #f) = #f
  attrs : null

procedure

(select options label #:attributes attrs)  widget/c

  options : radio-options/c
  label : string?
  attrs : null

procedure

(checkboxes options #:attributes attrs)  widget/c

  options : radio-options/c
  attrs : null
Return a widget that can render options in the given input type.

Examples:
> (define opts
    '(("high" . "Take the high road")
      ("low" . "Go low")))
> ((radios opts "Metaphorical highway selection") "road" #f null)

'(div

  ((class "group"))

  (label

   ((class "radio-group"))

   "Metaphorical highway selection"

   (div

    (label

     (input ((type "radio") (name "road") (value "high")))

     "Take the high road")

    (label (input ((type "radio") (name "road") (value "low"))) "Go low"))))

> ((checkboxes opts) "roadboxen" #f null)

'(div

  ((class "group"))

  (div

   ((class "div"))

   (label

    ()

    (input ((type "checkbox") (name "roadboxen") (value "high")))

    "Take the high road")

   (label

    ()

    (input ((type "checkbox") (name "roadboxen") (value "low")))

    "Go low")))

procedure

(make-autofill v)  xexpr?

  v : any/c
Renders a <meta> element whose content attribute varies depending on the current user: when the current user is a bot, it contains v serialized via write; otherwise the attribute is empty.

Use this when rendering step pages to instruct the bot how to fill in certain fields.

Examples:
> (make-autofill (hasheq 'example (hasheq 'name "Frank" 'mood "Delicate")))

'(meta ((name "formular-autofill") (content "")))

> (parameterize ([current-user-bot? #t])
    (make-autofill (hasheq 'example (hasheq 'name "Frank" 'mood "Delicate"))))

'(meta

  ((name "formular-autofill")

   (content

    "#hasheq((example . #hasheq((mood . \"Delicate\") (name . \"Frank\"))))")))

procedure

(make-autofill-meta ht)  xexpr?

  ht : hash?
Renders a <meta> element with name="formular-autofill" and a content attribute containing ht serialized via write. The autofill content is always included, regardless of the current user type.

Use this when rendering step pages to provide autofill instructions that should always be present in the page markup.

Example:
> (make-autofill-meta (hasheq 'example (hasheq 'name "Frank" 'mood "Delicate")))

'(meta

  ((name "formular-autofill")

   (content

    "#hasheq((example . #hasheq((mood . \"Delicate\") (name . \"Frank\"))))")))