Skip to content

Lesson 2: Simple forms

James Cheney edited this page Jun 19, 2017 · 7 revisions
fun handleForm(s,i) {
  page 
    <html>
      <body>
      <p>The string was: {stringToXml(s)}</p>
      <p>The integer was: {intToXml(i)}</p>
      </body>
    </html>
}

fun mainPage (_) {
  page 
    <html>
    <body>
      <h1>Example form</h1>
      <form l:action="{handleForm(s,stringToInt(i))}">
        A string: <input l:name="s" value="foo"/>
        An integer: <input l:name="i" value="42"/>
        <button type="submit">Submit!</button>
      </form>
      </body>
    </html>
}


fun main () {
  addRoute("",mainPage);
  servePages()
}

main()

This example illustrates how to create a form in Links and how to handle form submission. There are several ways to do this in Links:

  • HTML forms with submission handled by POSTing the form response to the server
  • HTML forms with submission handled by client-side (JavaScript) code
  • formlets, a higher-level abstraction for forms that allows for validation

This lesson is about the first approach, which is simplest and probably most familiar from other HTML or web programming settings. The form is defined in the mainPage function. This function creates a page that contains a submittable form. This is done largely as in ordinary HTML using the <form> tag to delimit the form, <input> tags to describe the form inputs, and the <button> tag to define a submission button.

There are also some important differences. In Links, there are special attributes that should be used with forms, so that Links can recognize and bind input values to Links variables, and likewise to give Links code that should be executed when the form is submitted. Consider the following lines:

      <form l:action="{handleForm(s,stringToInt(i))}">
        A string: <input l:name="s" value="foo"/>
        An integer: <input l:name="i" value="42"/>

The <input> tags includes an attribute l:name which is given value s in the string field and i in the integer field. Using this attribute means that when the form is submitted, Links will bind the value in the string field to s and bind the value of the integer field to 'i'. (The values are considered as strings in either case, since they are provided in a text field. For HTML forms, Links does not perform any validation.) The value attribute is just as in plain HTML: it gives the initial value of the field.

The <form> tag includes an attribute l:action whose value is a piece of Links code to be called when the form is submitted. The code is enclosed in {} braces in order to ensure Links parses it as Links code rather than as a string literal. Because the l:action field is used, the Links code is expected to return a page. (Unfortunately, the error message you get if this is wrong is quite opaque.)

The code in the l:action field is, in this case, a call to a function handleForm that constructs the page resulting from submitting the form. This code can refer to the variables s and i introduced in the form using l:name. Since they are both strings, we need to convert the integer parameter to an actual integer (this will fail if the submitted string doesn't parse to an integer).

The handleForm function simply constructs a new page that shows the submitted string and integer values. Both need to be coerced to XML strings using stringToXml or intToXml.

Exercises

  1. What happens if you leave off the l: prefix of the name attribute? Is the error message you get enlightening?

  2. What happens if you leave off the l: prefix of the action attribute? Is the error message you get enlightening?

  3. What happens if you leave off the curly braces in the l:action attribute value "{handleForm(s,stringToInt(i))}"?

  4. What happens if you return something other than a page from the l:action attribute value? For example, change to {(s,i)}?

  5. Experiment with including other standard HTML form elements such as textarea, radio, checkbox.