23. JavaScript Forms and Validation

What you will learn

  • How to read form values
  • How to handle the submit event
  • How to validate input and show accessible messages
  • Why server-side checks are still required

Reading form values

Every field has a value. It is always a string, even for number fields. Checkboxes use checked (true or false).

Handling submit

Listen for submit on the form, not for a click on the button. This also catches the Enter key. Call preventDefault() to take control.

Example

<form id="form">
  <label for="name">Name</label>
  <input id="name" type="text">
  <button type="submit">Send</button>
</form>
<p id="result"></p>

<script>
  document.getElementById("form").addEventListener("submit", function (event) {
    event.preventDefault();
    const name = document.getElementById("name").value.trim();
    document.getElementById("result").textContent = "Hello, " + name + "!";
  });
</script>

Output (run it in the editor)


A complete validation example

This form checks three fields, shows a message next to each problem, and tells screen readers about it with role="alert" and aria-invalid.

Example

<style>
  .field { margin-bottom: 12px; }
  .error { color: #b02a37; font-size: 0.9rem; min-height: 1.2em; }
  input[aria-invalid="true"] { border: 2px solid #b02a37; }
  .ok { color: #146c43; font-weight: bold; }
</style>

<form id="signup" novalidate>
  <div class="field">
    <label for="email">Email</label><br>
    <input id="email" type="email">
    <div class="error" id="email-error" role="alert"></div>
  </div>
  <div class="field">
    <label for="age">Age (13 to 120)</label><br>
    <input id="age" type="number">
    <div class="error" id="age-error" role="alert"></div>
  </div>
  <div class="field">
    <label for="pass">Password (at least 8 characters)</label><br>
    <input id="pass" type="password">
    <div class="error" id="pass-error" role="alert"></div>
  </div>
  <button type="submit">Sign up</button>
</form>
<p id="status" class="ok"></p>

<script>
  const form = document.getElementById("signup");

  function setError(id, message) {
    const input = document.getElementById(id);
    document.getElementById(id + "-error").textContent = message;
    if (message) { input.setAttribute("aria-invalid", "true"); }
    else { input.removeAttribute("aria-invalid"); }
    return message === "";
  }

  form.addEventListener("submit", function (event) {
    event.preventDefault();

    const email = document.getElementById("email").value.trim();
    const age = Number(document.getElementById("age").value);
    const pass = document.getElementById("pass").value;

    const emailOk = setError("email",
      /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(email) ? "" : "Enter a valid email address.");
    const ageOk = setError("age",
      Number.isInteger(age) && age >= 13 && age <= 120 ? "" : "Age must be a whole number from 13 to 120.");
    const passOk = setError("pass",
      pass.length >= 8 ? "" : "Password needs at least 8 characters.");

    document.getElementById("status").textContent =
      emailOk && ageOk && passOk ? "All good! (nothing was sent anywhere)" : "";
  });
</script>

Output (run it in the editor)




How it works

  1. novalidate turns off the browser’s own pop-up messages, so ours are shown.
  2. On submit we read each value and test it.
  3. setError shows or clears a message and sets aria-invalid, then reports whether the field passed.
  4. Only when all three pass do we show success.

Built-in validation

HTML can already check many things with required, type="email", min, max, minlength, and pattern. JavaScript can read the result with input.checkValidity() and input.validity, or show the browser’s message with form.reportValidity(). A good approach is to use these built-in rules first and add custom code only for what they cannot do.

Good validation practice

  • Label every field, and put the message next to it.
  • Say what is wrong and how to fix it.
  • Do not rely on colour alone. The message text carries the meaning.
  • Do not block valid but unusual input, such as names with apostrophes or long email addresses.

Security: validation in JavaScript only helps honest visitors. Anyone can bypass it. The server must always check the data again, and must never trust what the browser sends. You will practise this in the PHP course.

Common mistakes

  • Listening for the button’s click instead of the form’s submit.
  • Forgetting preventDefault(), so the page reloads.
  • Comparing a number field’s value without converting it from a string.
  • Showing errors only in red with no text.
  • Trusting client-side checks for security.

Exercise

When the form is submitted, stop the page reloading and show Too short if the username has fewer than 4 characters (after trimming), or Looks good otherwise.

Show solution
<form id="f" novalidate>
  <label for="user">Username (at least 4 characters)</label><br>
  <input id="user" type="text">
  <button type="submit">Check</button>
</form>
<p id="msg"></p>

<script>
  document.getElementById("f").addEventListener("submit", function (event) {
    event.preventDefault();
    const value = document.getElementById("user").value.trim();
    document.getElementById("msg").textContent =
      value.length < 4 ? "Too short" : "Looks good";
  });
</script>

Knowledge check

1. Which event should you listen for to handle a form?

submit, on the form element.

2. What type is the value of a number input?

A string.

3. Why must the server validate data too?

Client-side checks can be bypassed, so they cannot protect the server.

Summary

  • Listen for submit, call preventDefault(), and read values (always strings).
  • Show clear, accessible messages next to the fields.
  • Validate again on the server.
Scroll to Top