Form Validation

Back

Loading concept...

🛡️ Form Validation: The Bouncer at the Data Nightclub

Imagine you’re hosting the coolest party in town. But you can’t let just anyone in! You need a bouncer at the door who checks:

  • Is this person on the guest list? (required fields)
  • Are they wearing the right outfit? (pattern matching)
  • Do they have a valid ID? (data validity)

Form validation is your bouncer. It checks every piece of information before it gets into your app!


🎯 What You’ll Learn

graph TD A["Form Validation"] --> B["Basics"] A --> C["Validity State"] A --> D["checkValidity"] A --> E["setCustomValidity"] A --> F["Pattern Validation"] A --> G["Required Validation"] A --> H["FormData API"]

1️⃣ Form Validation Basics

What is it?

Form validation is like a spell-checker for user input. Before someone submits a form, we check:

  • Did they fill in the important stuff?
  • Is the email actually an email?
  • Is the phone number really a phone number?

Two Types of Validation

Type Where it happens Example
Client-side In the browser Instant feedback!
Server-side On the server Double-checking

Simple Example

<form id="partyForm">
  <input
    type="email"
    required
    placeholder="Your email">
  <button type="submit">
    Join Party!
  </button>
</form>

What happens? If you try to submit without an email, the browser says “Nope! Fill this in first!”

Why Both Sides?

Think of it like airport security:

  • 🏠 Client-side = Quick check at home before you leave
  • ✈️ Server-side = Real security at the airport

Never trust only client-side! Sneaky people can bypass it.


2️⃣ Validity State

The Report Card for Inputs

Every input field has a secret report card called ValidityState. It tells you exactly what’s wrong!

The Validity Properties

const input = document
  .querySelector('input');

// Get the report card
const validity = input.validity;
Property What it means
valid Everything is perfect! ✅
valueMissing Required field is empty
typeMismatch Wrong type (email, url)
patternMismatch Doesn’t match pattern
tooLong Too many characters
tooShort Too few characters
rangeOverflow Number too big
rangeUnderflow Number too small
stepMismatch Wrong step value
customError You set a custom error

Real Example

const email = document
  .getElementById('email');

email.addEventListener('input', () => {
  if (email.validity.typeMismatch) {
    console.log("That's not an email!");
  }
  if (email.validity.valueMissing) {
    console.log("Don't leave me empty!");
  }
  if (email.validity.valid) {
    console.log("Perfect! 🎉");
  }
});

Think of it like this: Each property is a different inspector checking one thing!


3️⃣ The checkValidity() Method

The Quick Yes/No Answer

Sometimes you just want to know: “Is this form okay or not?”

checkValidity() gives you a simple true or false.

On a Single Input

const nameInput = document
  .getElementById('name');

if (nameInput.checkValidity()) {
  console.log("Name is good! ✅");
} else {
  console.log("Name has problems! ❌");
}

On the Whole Form

const form = document
  .getElementById('myForm');

if (form.checkValidity()) {
  console.log("All fields are valid!");
  // Safe to submit!
} else {
  console.log("Something is wrong!");
}

The Secret Trigger

When checkValidity() fails, it fires an invalid event:

nameInput.addEventListener(
  'invalid',
  (e) => {
    console.log('Invalid!', e.target);
  }
);

// This triggers the event!
nameInput.checkValidity();

Pro tip: Use this to show custom error messages!


4️⃣ The setCustomValidity() Method

Create Your Own Rules!

What if the built-in checks aren’t enough? Make your own!

The Magic Spell

const password = document
  .getElementById('password');

password.addEventListener('input', () => {
  if (password.value.length < 8) {
    password.setCustomValidity(
      "Password needs 8+ characters!"
    );
  } else {
    // Clear the error!
    password.setCustomValidity("");
  }
});

⚠️ Super Important Rule!

You MUST clear the custom error when valid:

// Wrong - forgets to clear!
if (bad) {
  input.setCustomValidity("Error!");
}

// Right - always clear when good!
if (bad) {
  input.setCustomValidity("Error!");
} else {
  input.setCustomValidity(""); // Clear!
}

Password Matching Example

const pass = document
  .getElementById('password');
const confirm = document
  .getElementById('confirm');

confirm.addEventListener('input', () => {
  if (confirm.value !== pass.value) {
    confirm.setCustomValidity(
      "Passwords don't match!"
    );
  } else {
    confirm.setCustomValidity("");
  }
});

5️⃣ Pattern Validation

Regex: The Secret Code Checker

Patterns use regular expressions (regex). Think of them as a secret code that describes what’s allowed.

In HTML

<input
  type="text"
  pattern="[A-Za-z]{3,}"
  title="3+ letters only"
  placeholder="Your name">
Pattern What it allows
[A-Za-z]+ Only letters
[0-9]{5} Exactly 5 digits
\d{3}-\d{4} 123-4567 format
[a-z]+@[a-z]+\.[a-z]+ Simple email

Check Pattern in JavaScript

const phone = document
  .getElementById('phone');

phone.addEventListener('blur', () => {
  if (phone.validity.patternMismatch) {
    phone.setCustomValidity(
      "Use format: 555-1234"
    );
  } else {
    phone.setCustomValidity("");
  }
});

Phone Number Example

<input
  type="tel"
  pattern="\d{3}-\d{3}-\d{4}"
  title="Format: 123-456-7890"
  required>

Think of patterns like a lock: Only the right “key” (input format) opens it!


6️⃣ Required Validation

The “You MUST Fill This” Rule

The simplest validation. Just add required:

<input type="text" required>
<select required>
  <option value="">Pick one</option>
  <option value="a">Option A</option>
</select>
<textarea required></textarea>

Check if Required Field is Empty

const name = document
  .getElementById('name');

if (name.validity.valueMissing) {
  console.log("This field is required!");
}

Style Required Fields

/* Required fields get a star */
input:required {
  border-left: 3px solid red;
}

/* Valid required = green */
input:required:valid {
  border-left: 3px solid green;
}

/* Invalid = red glow */
input:invalid {
  box-shadow: 0 0 3px red;
}

Required vs Optional

<!-- Must fill -->
<input required placeholder="Email *">

<!-- Optional -->
<input placeholder="Nickname (optional)">

7️⃣ FormData API

The Easy Way to Grab All Data

Instead of getting each input one by one, FormData collects everything at once!

The Basic Spell

const form = document
  .getElementById('myForm');

form.addEventListener('submit', (e) => {
  e.preventDefault();

  const data = new FormData(form);

  // Get one value
  const name = data.get('name');

  // Get all values with same name
  const hobbies = data.getAll('hobby');
});

FormData Methods

Method What it does
get(name) Get one value
getAll(name) Get all values (checkboxes)
set(name, value) Change a value
append(name, value) Add new value
delete(name) Remove a field
has(name) Check if exists
entries() Loop through all

Loop Through Everything

const data = new FormData(form);

for (const [key, value] of data) {
  console.log(`${key}: ${value}`);
}

Send to Server

const form = document
  .getElementById('myForm');

form.addEventListener('submit',
  async (e) => {
    e.preventDefault();

    if (!form.checkValidity()) {
      return; // Stop if invalid!
    }

    const data = new FormData(form);

    await fetch('/api/submit', {
      method: 'POST',
      body: data
    });
});

Convert to Object

const data = new FormData(form);
const obj = Object.fromEntries(data);

console.log(obj);
// { name: "Sam", email: "sam@test.com" }

🎬 Putting It All Together

Here’s a complete example with everything we learned:

<form id="signupForm">
  <input
    id="email"
    type="email"
    name="email"
    required
    placeholder="Email *">

  <input
    id="password"
    type="password"
    name="password"
    pattern=".{8,}"
    required
    placeholder="Password (8+ chars) *">

  <input
    id="confirmPass"
    type="password"
    required
    placeholder="Confirm Password *">

  <button type="submit">Sign Up</button>
</form>
const form = document
  .getElementById('signupForm');
const password = document
  .getElementById('password');
const confirm = document
  .getElementById('confirmPass');

// Custom: passwords must match
confirm.addEventListener('input', () => {
  if (confirm.value !== password.value) {
    confirm.setCustomValidity(
      "Passwords don't match!"
    );
  } else {
    confirm.setCustomValidity("");
  }
});

// Handle submit
form.addEventListener('submit', (e) => {
  e.preventDefault();

  if (!form.checkValidity()) {
    form.reportValidity();
    return;
  }

  const data = new FormData(form);
  console.log("Submitting:",
    Object.fromEntries(data)
  );
});

🧠 Quick Memory Tricks

Concept Remember it as…
validity The report card 📋
checkValidity() Quick pass/fail ✅❌
setCustomValidity() Your own rules 📝
pattern The secret code 🔐
required Must have! ⭐
FormData The collector 🎒

🎉 You Did It!

You now know how to:

  • ✅ Validate forms on the client side
  • ✅ Check validity state of any input
  • ✅ Use checkValidity() for yes/no answers
  • ✅ Create custom rules with setCustomValidity()
  • ✅ Enforce patterns with regex
  • ✅ Make fields required
  • ✅ Collect all form data easily with FormData

Remember: Form validation is your friendly bouncer. It keeps bad data out and makes sure only the right guests get into your app! 🎊

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.