Home/Learn/JavaScript & TypeScript/Forms — Inputs, Validation and Submission

Forms — Inputs, Validation and Submission

Intermediate
The Browser

Forms are where most user data enters an application. The browser gives you validation, keyboard handling and accessibility free — if you use a real form element rather than a div with a button.

Overview

It is tempting to build a form out of divs and handle everything in JavaScript, and it is almost always the wrong call. A real form element gives you Enter-to-submit, browser validation, autofill, and correct screen-reader behaviour with no work. What you add is the submit handler, which should call preventDefault and take over from there. FormData reads every named field in one line, which is far less brittle than reading each input by id.

Reading a Form

FormData collects every named field, including files. It is the reason forms need name attributes.

FormData, and why name attributes matter
form.addEventListener('submit', async (e) => {
  e.preventDefault()                     // stop the page navigating

  const data = new FormData(form)
  data.get('email')                      // by name attribute
  Object.fromEntries(data)               // plain object, for JSON APIs

  await fetch('/api/signup', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(Object.fromEntries(data)),
  })
})

// Sending files: pass the FormData directly, no Content-Type header
await fetch('/api/upload', { method: 'POST', body: new FormData(form) })

// Checkboxes and multi-selects need getAll
data.getAll('topics')     // ['arrays', 'graphs']

Browser Validation

Constraint attributes give you validation and messaging for free. You can style the states and override the messages.

Constraints, and :user-invalid
<input type="email" name="email" required />
<input type="password" name="pw" minlength="8" required />
<input type="number" name="qty" min="1" max="10" />
<input type="text" name="pin" pattern="[0-9]{6}" />

// Checking from JavaScript
input.checkValidity()          // boolean
form.reportValidity()          // shows the browser's messages
input.validity.tooShort        // which rule failed

// Custom message
input.setCustomValidity(
  input.validity.patternMismatch ? 'PIN must be 6 digits' : ''
)

// Styling states
input:invalid { border-color: red }
input:user-invalid { ... }     // only after the user has interacted

Controlled Inputs

The pattern React uses: state is the source of truth, the input reflects it, and every keystroke updates state.

Controlled inputs and server errors
// Vanilla equivalent of a controlled input
let value = ''
input.value = value
input.addEventListener('input', (e) => {
  value = e.target.value        // state updates
  render()                      // UI follows state
})

// Server validation errors, mapped back to fields
const res = await fetch('/api/signup', { ... })
if (res.status === 422) {
  const { errors } = await res.json()
  for (const [field, message] of Object.entries(errors)) {
    form.elements[field].setCustomValidity(message)
  }
  form.reportValidity()
}

// Always disable the submit button while in flight,
// or an impatient double-click creates two accounts.

Key Points to Remember

  • 1A real form element gives Enter-to-submit, validation, autofill and screen-reader support for free
  • 2preventDefault in the submit handler stops the page navigating away
  • 3FormData reads every named field at once — which is why inputs need name attributes, not just ids
  • 4Constraint attributes (required, minlength, pattern) provide validation without JavaScript; :user-invalid styles only after interaction
  • 5Disable the submit button while the request is in flight, or a double-click submits twice

Interview Questions

Sign in to ask Aria
1

Why use a <form> element instead of a div with a submit button?

Easy
2

How do you read all values from a form in one step?

Easy
3

How would you map server-side validation errors back onto individual form fields?

Medium

Ask Aria about Forms — Inputs, Validation and Submission

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…