What you'll be able to do

By the end of this page you should be able to read text field values, tell empty string from “missing,” handle checkboxes, and block obvious bad input before you send data anywhere.

Previous post: create elements and lists.

Who this is for

  • People who submit forms and get "" when they expected null
  • Beginners wiring a login or signup demo
  • Anyone who needs client-side checks before fetch (fetch comes later)

You can skip this if form APIs already feel boring. Come back when “required” in HTML is not enough for your UX message.

Text inputs: .value

const email = document.querySelector("#email");
console.log(email.value); // always a string, often ""

Scenario A — empty field. Value is "", not null. Test with email.value.trim() === "".

Scenario B — whitespace-only. .trim() before validation.

Empty string vs null (mental model)

HTML inputs give strings. “No text” means "". null usually means “no object” or “missing property” in JS data — not what a blank <input> returns.

Scenario A — optional nickname. Empty string is fine; store or skip explicitly.

Scenario B — API expects null for missing. Convert on submit: name || null only if the API contract says so.

Checkboxes and numbers

const agree = document.querySelector("#agree");
console.log(agree.checked); // boolean

const age = document.querySelector("#age");
const n = Number(age.value); // NaN if not a number

Scenario A — terms checkbox. Block submit if !agree.checked.

Scenario B — age field. Number + Number.isNaN before math.

Light validation pattern

function validateEmail(raw) {
  const value = raw.trim();
  if (value === "") return "Email is required.";
  if (!value.includes("@")) return "Email looks incomplete.";
  return "";
}

Scenario A — show message under the field.

Scenario B — prevent submit when message is non-empty. Real security validation still belongs on the server — this is UX and early feedback.

Form submit event

document.querySelector("form").addEventListener("submit", function (event) {
  event.preventDefault();
  // read fields, validate, then maybe fetch later
});

Scenario A — stay on page for a SPA-style demo.

Scenario B — full page reload. Omit preventDefault when classic form POST is what you want.

A tiny practice file

Save as form-input.html.

<!DOCTYPE html>
<html>
  <body>
    <form id="signup">
      <input id="name" placeholder="Name" />
      <p id="err" style="color:crimson"></p>
      <button type="submit">Save</button>
    </form>
    <pre id="out"></pre>
    <script>
      document.getElementById("signup").addEventListener("submit", function (e) {
        e.preventDefault();
        const name = document.getElementById("name").value.trim();
        const err = document.getElementById("err");
        if (name === "") {
          err.textContent = "Name is required.";
          return;
        }
        err.textContent = "";
        document.getElementById("out").textContent = "Hello, " + name;
      });
    </script>
  </body>
</html>

Mistakes I see a lot

1. Checking if (!input.value) without .trim().

2. Expecting null from an empty text input.

3. Forgetting type="submit" fires form submit — button inside form submits by default.

4. Trusting client validation alone.

5. Reading checkbox with .value instead of .checked.

What to try before the next post

  1. Log value for empty vs filled input.
  2. Validate trimmed name; show inline error.
  3. Read a checkbox on submit.
  4. Build form-input.html.

Next in this series: events and listeners — clicks, preventDefault, and avoiding double-bound handlers.

Try this next outside the series

Browser JavaScript stops feeling isolated once you connect it to forms and component-oriented UI work.