# An ugly page that exercises the various types of input fields in a form.
fun radioGroupVertical(items) {
for((xml, label) <- items)
<#>
{xml} {stringToXml(label)}
#>
}
var theFormlet =
formlet
<#>
Style of bike: { choice([(1, "Road bike"),
(2, "Mountain Bike"),
(77, "Hybrid")]) -> bikeStyle }
Add-ons: { choicesNone([(2, "Bell"),
(3, "Rack"),
(6, "Glow-in-the-dark handlebar tape")]) -> addons }
{ inputRadiogroup(["Red", "Green", "Blue"], "Blue", radioGroupVertical)
-> colour }
Comments about your order:
{ textarea("Comments") -> comments }
Over 65? { checkbox -> over65 }
Upload a file: { inputFile -> file }
{ submitButton("Check Out") -> checkout }
{ submitButton("Cancel") -> cancel }
#>
yields
(bikeStyle=bikeStyle,
comments=comments,
over65=over65,
cmd=if (checkout) Checkout else if (cancel) Cancel else NoButton,
addons=addons,
colour=colour,
file=file);
sig stringConcat : (String, [String]) ~> String
fun stringConcat(delimiter, ss) {
switch (ss) {
case [] -> ""
case [s] -> s
case s::ss -> s ^^ delimiter ^^ stringConcat(delimiter, ss)
}
}
fun renderer (formData) {
page
{if (formData.cmd == Checkout)
<#>
Bike style code: {intToXml(formData.bikeStyle)}
Add-ons: {stringToXml(stringConcat(", ", map(intToString, formData.addons)))}
Colour: {stringToXml(formData.colour)}
Comments: {stringToXml(formData.comments)}
{stringToXml(if (formData.over65) "A senior cyclist! Way to go!" else "")}
File: {stringToXml(formData.file)}
#>
else
<#>Order Cancelled. Thanks for visiting!#>}
}
fun main() {
page
<#>{theFormlet => renderer with multipart}#>
}
main()