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.
<form action="/path/to/endpoint" method="GET"> <input type="text" name="inName1" /> <input type="text" name="inName2" /> <input type="submit" /> </form>
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
Recall that HTTP
GET requests do not have body content. When a form is
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
inName2 respectively, then on submit, the browser would
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
If instead we change the form’s method to
POST, it will send an HTTP request
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
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.
As seen above, forms use the encoding
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
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 😄
For forms with a
POST action, we can also choose a different encoding type:
multipart/form-data. This is specified using a
attribute. We can modify our previous example to use this combination of action
<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
inName2 respectively, the browser will send an HTTP request that appears
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.
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
type attribute, and are rendered as single-line boxes. An overview
of some of the most common types is listed below.
||password; text is hidden or obscured after input|
||numeric; user can type in numbers or use an up/down stepper to change the value|
||toggle an input between selected and unselected states independent of other input states|
||used in a radio group to check only one option from many|
||upload files from the user’s device’s filesystem|
||choose a date and time, often rendered as a calendar-like datepicker|
||used to submit a named field with the form that is not visible to the user|
||renders a button that triggers form submission on click|
||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:
||multi-line text input|
||drop-down selection UI|
||render a button which can be of type
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
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.