Version: 4.1.4
2.10.1 Basic Formlet Usage

Suppose we want to create an abstraction of entering a date in an HTML form. The following formlet captures this idea:

  (define date-formlet
    (formlet
     (div
      "Month:" ,{input-int . => . month}
      "Day:" ,{input-int . => . day})
     (list month day)))

The first part of the formlet syntax is the template of an X-expression that is the rendering of the formlet. It can contain elements like ,(=> formlet name) where formlet is a formlet expression and name is an identifier bound in the second part of the formlet syntax.

This formlet is displayed (with formlet-display) as the following X-expression forest (list):

  (list
   '(div "Month:" (input ([name "input_0"]))
         "Day:" (input ([name "input_1"]))))

date-formlet not only captures the rendering of the form, but also the request processing logic. If we send it an HTTP request with bindings for "input_0" to "10" and "input_1" to "3", with formlet-process, then it returns:

  (list 10 3)

which is the second part of the formlet syntax, where month has been replaced with the integer represented by the "input_0" and day has been replaced with the integer represented by the "input_1".

The real power of formlet is that they can be embedded within one another. For instance, suppose we want to combine two date forms to capture a travel itinerary. The following formlet does the job:

  (define travel-formlet
    (formlet
     (div
      "Name:" ,{input-string . => . name}
      (div
       "Arrive:" ,{date-formlet . => . arrive}
       "Depart:" ,{date-formlet . => . depart})
     (list name arrive depart))))

(Notice that date-formlet is embedded twice.) This is rendered as:

  (list
   '(div
     "Name:"
     (input ([name "input_0"]))
     (div
      "Arrive:"
      (div "Month:" (input ([name "input_1"]))
           "Day:" (input ([name "input_2"])))
      "Depart:"
      (div "Month:" (input ([name "input_3"]))
           "Day:" (input ([name "input_4"]))))))

Observe that formlet-display has automatically generated unique names for each input element. When we pass bindings for these names to formlet-process, the following list is returned:

  (list "Jay"
        (list 10 3)
        (list 10 6))

The rest of the manual gives the details of formlet usage and extension.