Fundamentals of Web Application Development · DRAFTFreeman

Forms

Accepting User Input

So far, all of the examples we’ve seen have carried information primarily in one direction: from the server to the client. In most web applications we want the ability for information to flow in the other direction as well.

There is one kind of input that we have already seen: the URL of the page to load. The server’s response (the page that is loaded) depends on the URL provided by the client, potentially including path and query parts. See § Uniform Resource Locators if you need a refresher on the aspects of URLs, as these will come into play in this chapter.

The form Element

<form action="/path/to/endpoint" method="GET">
  <input type="text" name="inName1" />
  <input type="text" name="inName2" />
  <input type="submit" />
</form>

Actions

When a form is submitted, the browser sends a new HTTP request to the URL specified in the form’s action attribute. The method attribute specifies which HTTP method to use: either GET (the default if not specified) or POST.

Recall that HTTP GET requests do not have body content. When a form is submitted with GET, the values input to the form are added as query parts on the end of the URL. For example, if we typed “value1” and “value2” into the inputs inName1 and inName2 respectively, then on submit, the browser would send a GET request that appears like

GET /path/to/endpoint?inName1=value1&inName2=value2 HTTP/1.1
Host: example.com

(assuming that the form is on a page under the domain example.com).

If instead we change the form’s method to POST, it will send an HTTP request such as

POST /path/to/endpoint HTTP/1.1
Host: example.com
Content-Length: 29
Content-Type: application/x-www-form-urlencoded

inName1=value1&inName2=value2

Notice that the same string of name-value pairs is included, this time in the body of the request. The request itself is sent to the URL specified in action, with no additional query parameters.

The choice of GET vs. POST depends on the functionality you want it to serve. Typically, the GET method implies that a given HTTP request will not mutate application state on the server. It is appropriate for use cases like searching through a list or database of existing items, where a user might submit a form with search terms, selected filters, and pagination parameters. Because forms using the GET method append their inputs as query parts on the URL, they will appear in the user’s browser history, can be bookmarked, and can be shared with other people as links. For the same reason, it is inappropriate to use the GET method when submitting passwords or other sensitive information, or when the size of the input is expected to be thousands of characters or more.

In contrast, forms using the POST method do not surface their information visibly to the user. Because the input data are sent in the body of the request, it can also be of arbitrary length and type, including files and other binary data, as discussed below. POST requests often imply modification of application state, and most browsers implement prompts for confirmation to prevent users from accidentally submitting the same POST form multiple times.

In either case, when a form is submitted, control is passed to the server. What the server does with incoming requests with form data is outside the scope of this text, but most server-side libraries and frameworks include their own utilities for parsing and processing form submissions.

In the browser, submission of the form is treated as a new navigation request, which means that the current page will be unloaded and the received response document will be loaded as a new page, undergoing all of the page rendering steps we previously discussed – parsing HTML, building the DOM, fetching other external resources such as CSS and JavaScript, and so on. In a later chapter, we will look at other ways to send data from the browser to a server without triggering an entirely new page load.

Encoding

URL Encoding

As seen above, forms use the encoding application/x-www-form-urlencoded by default. This instructs the server to parse the included data as a URL-encoded string of name-value pairs. URL encoding converts arbitrarily-formatted text (usually UTF-8) into a subset of ASCII characters which can be safely used in URLs.

For normal forms, the browser does this encoding automatically before it is submitted. JavaScript has builtin functions to URL-encode and decode arbitrary strings as well.

encodeURIComponent('hello world, & everyone 😄');
// hello%20world%2C%20%26%20everyone%20%F0%9F%98%84

decodeURIComponent('hello%20world%2C%20%26%20everyone%20%F0%9F%98%84');
// hello world, & everyone 😄

Multipart Form Data

For forms with a POST action, we can also choose a different encoding type: multipart/form-data. This is specified using a form element’s enctype attribute. We can modify our previous example to use this combination of action and encoding:

<form action="/path/to/endpoint" method="POST" enctype="multipart/form-data">
  <input type="text" name="inName1" />
  <input type="text" name="inName2" />
  <input type="submit" />
</form>

Now, when we submit the form with “value1” and “value2” for the inputs inName1 and inName2 respectively, the browser will send an HTTP request that appears as

POST /path/to/endpoint HTTP/1.1
Host: example.com
Content-Type: multipart/form-data;boundary="theboundary"

--theboundary
Content-Disposition: form-data; name="inName1"

value1
--theboundary
Content-Disposition: form-data; name="inName2"

value2
--theboundary--

Each input name and value are included as a “part” of the request body, each part separated by a boundary token generated by the sending client. Multipart encoding is required for the user to submit and upload files, discussed below.

Inputs

Standard Types of Input

Various kinds of user input can be collected using specific types of elements inside of a form element. Most kinds of input use an input element with a specified type attribute, and are rendered as single-line boxes. An overview of some of the most common types is listed below.

type description
text single-line text
search same as text, but hints for the browser to style it in a distinguishable way
email email address
password password; text is hidden or obscured after input
number numeric; user can type in numbers or use an up/down stepper to change the value
tel telephone number
url URL address
checkbox toggle an input between selected and unselected states independent of other input states
radio used in a radio group to check only one option from many
file upload files from the user’s device’s filesystem
datetime-local choose a date and time, often rendered as a calendar-like datepicker
hidden used to submit a named field with the form that is not visible to the user
submit renders a button that triggers form submission on click
reset button that clears all non-hidden inputs in the same form

The default type – if none is specified, or the browser doesn’t support the given type – is text. Many other input types visually appear as a text input while giving the browser more semantic information about the nature of the data it is supposed to accept, which allows it to provide functionality like autocomplete, alternative keyboards on touch screens, and format validation.

A few kinds of inputs work using different elements:

element description
textarea multi-line text input
select drop-down selection UI
button render a button which can be of type submit, reset, or invoke arbitrary JavaScript execution

Labels

A label element provides a caption for a given form control. To associate a label with a form control, its for attribute is set to the ID of the control element. For example,

<input id="fName" type="text" name="firstName" />
<label for="fName">First Name</label>

Note that the association uses the control element’s id attribute and not name (they are unrelated, though they could be the same string).

Inputs can also be placed inside of their own labels:

<label for="fName">
  First Name
  <input id="fName" type="text" name="firstName">
</label>

Though these visually appear as normal text and could be similarly rendered using spans or other inline elements, label elements provide important semantic value to the controls which they label. The browser programmatically ties label elements to their controls, allowing screen readers and other assistive technologies to better interpret their association, and also allowing users to focus or select an input by clicking on its label. It is important that every user-accessible input in a form have an accompanying label.

Client-Side Input Validation