Command Palette

Search for a command to run...

Hectal
PHASE 4Intermediate ~20 min· topic 1 of 8

Topic 4.1

How Forms Work

In one line

A <form> collects the values of its named controls and, when submitted, sends them to the URL in action using the HTTP method in method: GET puts them in the URL, POST puts them in the request body.

Think of it like this

Filling in a paper form at the post office. Each box has a printed label ("Name", "Address"). You write in the boxes, then hand the whole sheet to the clerk at a particular counter. The form is the sheet, each box is a control, the printed box name is the name attribute, and the counter you hand it to is the action URL.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Form
The <form> element: a group of controls whose values are sent together.
Control
Something a person fills in or chooses, such as an <input>, <select>, <textarea> or <button>.
Submit
To send the form: the browser gathers the values and makes a request to the server.
action
The form attribute that holds the URL the data is sent to.
method
The form attribute that picks how data is sent: get (in the URL) or post (in the request body).
name attribute
The label a control's value is sent under. No name means the value is not sent.
Query string
The part of a URL after ?, made of name=value pairs joined by &.
Percent-encoding
Writing special characters as % plus a code, like %26 for &, so they can travel safely in a URL.
Request body
The data part of an HTTP request, sent after the headers. POST forms put their pairs here.

Step by step

01A form with one field

Here is the smallest useful form: a search box and a button. The <input> has name="q" (short for query), so its value is sent as q=.... The button submits the form when clicked.

index.htmlwhole filehtml
<form action="/search" method="get">
  <input name="q">
  <button>Search</button>
</form>

02Submitting with GET

Type cats & dogs and press the button. The browser builds the query string q=cats+%26+dogs (the space became +, the & became %26) and goes to /search?q=cats+%26+dogs.

The server reads the query string, finds the results and sends back a new page. You can bookmark that URL and get the same search later.

HTTP requestwhole filehttp
GET /search?q=cats+%26+dogs HTTP/1.1
Host: example.com

03Submitting with POST

Change the form to method="post" and add a password field. Now the URL is only /login, and the pairs travel in the body. The Content-Type header tells the server how the body is packed.

HTTP requestwhole filehttp
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

user=asha&password=s3cret

04What decides what gets sent

The browser walks the form's controls in page order and keeps a pair for each one that has a name, is not disabled, and (for checkboxes and radio buttons) is ticked. Everything else is left out. The button that was clicked is also sent if it has a name.

What decides what gets sentdiagram
Rendering diagram…

05The round trip

After a normal submit, the browser leaves the page and shows whatever the server answers. That is why, later in the JavaScript course, you'll learn to stop the default submit with event.preventDefault() and send the data with fetch instead, so the page can stay put.

The round tripdiagram
Rendering diagram…

Try it yourself

  1. 1

    Predict the query string

    In the first example, change the q value to 100% cotton. Before you run it, write down what you think the query string will be. Then run it. (The % itself must be encoded, as %25, and the space becomes +: q=100%25+cotton.)

  2. 2

    Give the nameless field a name

    Add name="note" to the third input in the first example. Predict where the new pair appears in the query string, then run it. Pairs follow the order of the fields in the page.

  3. 3

    Enable the disabled field

    In the second example, remove disabled from the ref input. Run it: ref = home now appears in the console and in the body.

Code & diagrams

What a GET form would send New tab

`FormData` collects exactly what the browser would send. Press Search too: the preview logs the submitted pairs instead of leaving the page.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Method: get
Action: /search
Query string: q=cats+%26+dogs&lang=en
Full URL: /search?q=cats+%26+dogs&lang=en
A POST form, caught before it leaves New tab

The disabled `ref` field is not sent. `requestSubmit()` submits the form the same way a click on the button does.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Method: post
user = asha
password = s3cret
Body would be: user=asha&password=s3cret
GET or POST?diagram
Rendering diagram…

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Forget the name attributes

In the second example, delete the form.requestSubmit(); line and remove name="user" and name="password", then click Log in.

terminal
$ Console
── what you'll see ──
Method: post
Body would be:

Break #2

Send a password with GET

Change a login form to method="get" and submit it on a real site you run locally.

terminal
$ Address bar
── what you'll see ──
/login?user=asha&password=s3cret

Myth vs fact

Myth

POST is secure and GET is not.

Fact

Both are sent in plain text unless the page uses HTTPS. POST only keeps the data out of the URL, history and logs; HTTPS is what encrypts it.

Myth

Every input in the form is sent.

Fact

Only controls with a name that are not disabled are sent, and checkboxes and radio buttons only when ticked.

Myth

You need JavaScript to send a form.

Fact

HTML forms submit on their own. JavaScript is optional, used when you want to stay on the page or check things first.

Myth

The id attribute is what the server receives.

Fact

The server receives the name. id is for labels, CSS and JavaScript inside the page.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    When method="get", the browser replaces any query string already in action: action="/s?x=1" loses x=1. Put fixed values in hidden inputs instead (Topic 4.5).

  • ▸

    Reloading a page that was the answer to a POST asks "Confirm form resubmission", because repeating it could, say, place an order twice. Servers avoid this with Post/Redirect/Get: answer the POST with a 303 See Other redirect to a normal GET page. See the System Design course (/system-design) for idempotency and HTTP methods.

  • ▸

    FormData is the browser's own algorithm for "what would be submitted" (it is the spec's form data set). new FormData(form, submitter) also includes the clicked button's pair. URLSearchParams produces the same application/x-www-form-urlencoded string the browser sends.

  • ▸

    There is no fixed URL length limit in the HTML spec, but servers and proxies often reject URLs over about 8 KB, so large or many fields belong in a POST body.

Remember this

  1. 1

    A form is the <form> element plus the controls inside it. A control is anything a person can fill in or choose: <input>, <select>, <textarea>, <button>. When the form is submitted (sent), the browser gathers the controls' values and makes an HTTP request to a server, just like clicking a link, except it carries data with it.

  2. 2

    The action attribute is the URL the data is sent to, for example action="/search". If you leave it out, the form is sent to the address of the current page. The method attribute is the HTTP method: get (the default) or post. (There's also method="dialog", which closes a <dialog> instead of sending anything; you met <dialog> in Topic 2.6.)

  3. 3

    Only controls with a **name attribute are sent. Each one becomes a name/value pair** such as q=cats. A control without a name is still shown and can be typed into, but its value never leaves the page. Disabled controls, unticked checkboxes and unselected radio buttons are skipped too. The browser builds this list in the order the controls appear in the page.

  4. 4

    With GET, the pairs are joined with & and added to the URL after a ?. That part of the URL is the query string: /search?q=cats&lang=en. Spaces become + and characters with special meaning, like & or =, are percent-encoded (& becomes %26) so the server can split the pairs correctly. GET results can be bookmarked, shared and cached, which is perfect for searches and filters.

  5. 5

    With POST, the same pairs travel in the request body, the part of the HTTP request after the headers, and the URL stays clean. Use POST for anything that changes something on the server (sign up, place an order, post a comment) and for anything private, like passwords, which must never end up in a URL, browser history or server logs. POST is not encryption: only HTTPS protects the data on the way.

  6. 6

    How the pairs are packed is set by enctype (encoding type). The default, application/x-www-form-urlencoded, is the name=value&name=value format. File uploads need enctype="multipart/form-data", which sends each field as a separate part (Topic 4.5). Whatever the format, the server receives plain text it must check: the browser never guarantees what arrives (Topic 4.7).

Explain it without notes

01

Walk through what happens when someone presses Submit on a form with method="get".

02

When would you choose GET and when POST for a form? Give an example of each.

03

Which controls in a form are included in the submitted data, and which are skipped?

04

Why do spaces and & signs need encoding in a query string?

Practice

01

Write a GET form that sends a product search to /products with two fields: q (the search text) and sort with the value price. What URL does searching for red shoes produce?

02

Write a POST form that sends a comment to /comments with fields author and text, and log what it would send using FormData.

Trade-offs

  • ↔

    GET makes results shareable and cacheable but exposes data in the URL and limits size; POST hides data from the URL and handles large bodies but can't be bookmarked and warns on reload.

  • ↔

    A plain HTML submit works without JavaScript and is very robust, but reloads the page; submitting with fetch keeps the page in place but needs JavaScript and your own error handling.

Done when you can

  • I can write a form with action and method.

  • I can say which controls are sent and which are skipped.

  • I can predict the query string a GET form produces, including encoding.

  • I can choose between GET and POST and explain why.

  • I can inspect what a form would send with FormData.