[plt-scheme] Formlets in PLT
The Links group has created formlets:
http://groups.inf.ed.ac.uk/links/formlets/
I have spent the afternoon implementing formlets in PLT.
--
In the latest SVN, there is a web-server/formlets directory with a
'formlets' module.
Here is a simple example:
==== Define some basic functions & structures
#lang scheme
(require web-server/formlets/formlets)
(define-struct date (month day))
(define (date->xml d)
(format "~a/~a"
(date-month d)
(date-day d)))
(define (submit t)
`(input ([type "submit"]) ,t))
==== Now for the first formlet:
(define date-formlet
(formlet
(div
"Month:" ,{input-int . => . month}
"Day:" ,{input-int . => . day})
(make-date month day)))
==== The first part is the display of the formlet, the second is how
it should be processed. The => syntax tells the formlet macro that
month and day should be bound in the processor as the result of
inputing integers.
(formlet-display date-formlet)
==== Displaying this formlet returns the following xexpr forest (list):
((div () "Month:" (input ((name "input_0"))) "Day:" (input ((name "input_1")))))
==== The input names are automatically generated.
==== Formlets can be composed:
(define travel-formlet
(formlet
(#%#
"Name:" ,{input-string . => . name}
(div
"Arrive:" ,{date-formlet . => . arrive}
"Depart:" ,{date-formlet . => . depart})
,@(list "1" "2" "3")
,(submit "Submit"))
(list name arrive depart)))
==== The #%# is to note an xexpr forest. Notice that date-formlet is
used to embed the date formlet twice in the travel formlet. The
display portion of a formlet is implicitly in a quasiquote, so ,@ and
, work as before.
(formlet-display travel-formlet)
==== The travel formlet is displayed as follows:
("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")))))
"1"
"2"
"3"
(input ((type "submit")) "Submit"))
==== Notice the input names are guaranteed to not conflict.
==== Let's embed this formlet into a web page that does the following
with the result:
(define display-itinernary
(match-lambda
[(list name arrive depart)
`(html
(head (title "Itinerary"))
(body
"Itinerary for: " ,name
"Arriving:" ,(date->xml arrive)
"Departing:" ,(date->xml depart)))]))
==== This provides send/formlet, which wraps a formlet in send/suspend
(require web-server/formlets/servlet)
(define (start request)
(display-itinernary
(send/formlet
travel-formlet)))
==== embed-formlet is also available to put a formlet inside of
send/suspend/dispatch
--
Currently formlet combinators are provided for input-string,
input-integer, and input-symbol. More will come as the library is
used. I also plan on working on input validation, etc.
Jay
--
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://jay.teammccarthy.org
"The glory of God is Intelligence" - D&C 93