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 span
s 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.