What a form does
Which controls are submitted
Identify successful form controls and understand why disabled, unnamed, unchecked, or unselected controls may be absent from submitted data.
Not every control inside a form ends up in the request. The browser only sends the successful controls. That is the spec’s term for the controls that qualify to be submitted.
Let’s look at a form that mixes both kinds:
<form action="/preferences" method="post">
<input name="displayName" value="Ada">
<input value="not sent">
<input name="accountId" value="42" disabled>
<label>
<input name="newsletter" type="checkbox" value="yes">
Join the newsletter
</label>
<button name="action" value="save">Save</button>
</form>
Submit it as is and the body contains displayName=Ada&action=save. Nothing else.
Here is why each missing control is missing:
- the second input has no
name, so there’s no key to send it under accountIdisdisabled, and disabled controls are never submitted- the checkbox is unchecked, and an unchecked checkbox sends nothing at all
action=saveis there only because that button started the submission
Check the newsletter box and submit again. Now you get newsletter=yes too. Uncheck it and the key disappears from the body. It doesn’t become newsletter= or newsletter=no. It’s gone.
Absence means different things
This matters when you write the server side. A missing newsletter probably means “not selected”. A missing displayName on a form that requires it is an error.
Don’t write a parser that turns every missing key into an empty string. Decide what absence means for each field, based on what the endpoint expects.
Disabled is not protection
I’ve seen disabled used to lock a value the user shouldn’t change, like an account ID. That protects nothing. It also breaks the form, because the value is never sent.
A visitor can edit the HTML in DevTools and remove disabled. They can also build the request by hand and send accountId=1. If the server already knows the account ID from the session or the URL, use that. Never accept it from the form.
Read-only is different
readonly looks similar but behaves differently. A read-only text control can’t be edited, but it is submitted:
<input name="plan" value="pro" readonly>
This sends plan=pro. It’s fine for showing a value the person can see but not edit. The server still has to verify it, because readonly is just as easy to remove in DevTools as disabled.
Try this with the Network panel open: submit the form with the checkbox unchecked, then checked. Compare the two payloads and notice what’s absent, not just what’s there.
Lesson completed