Topic 43 of 48 · Full Stack Essentials

JavaScript Validation

Lesson TL;DRTopic 6: JavaScript Validation 📖 16 min read · 🎯 intermediate · 🧭 Prerequisites: divpagedesign, formsubmissiontask Why this matters You've filled out a form online — typed your email, set a passwor...
16 min read·intermediate·javascript · form-validation · client-side · regex

Topic 6: JavaScript Validation

📖 16 min read · 🎯 intermediate · 🧭 Prerequisites: div-page-design, form-submission-task

Why this matters

You've filled out a form online — typed your email, set a password, clicked Submit — and the page just accepted gibberish. A phone number in the email field. A one-letter password. No warning, no pushback. That feels wrong, and it is.

JavaScript validation is the code that checks user input before it goes anywhere. It's your first line of defence against typos, accidents, and incomplete data. In this lesson, you'll learn how to write that check yourself — so your forms actually guide the user instead of silently accepting whatever they type.

What You'll Learn

  • Distinguish client-side validation from server-side validation and know when each applies
  • Implement basic form validation in JavaScript to ensure required fields are not empty
  • Use regular expressions to validate email format and phone number format
  • Enforce password length and confirm-password matching in an advanced registration form

The Analogy

Think of JavaScript validation as the security check at an airport departure gate. Before your luggage ever reaches the aircraft (the server), a gate agent (the browser) inspects it against a checklist: Does it have a tag? Is it within the weight limit? Does the name on the ticket match the ID? Only bags that pass every check are loaded onto the plane. If something is wrong, the problem is caught right there at the gate — cheaply and quickly — rather than halfway across the ocean where fixing it is expensive and embarrassing. Client-side validation is that gate agent: fast, immediate, and working entirely on the ground before anything takes flight.

Chapter 1: The Importance of Validation

Validation is the process of ensuring that the data entered by users meets certain criteria before it is processed. This protects against errors, security issues, and data inconsistencies that would otherwise reach your database or business logic.

Validation falls into two fundamental categories:

  • Client-Side Validation — performed in the browser before the data is sent to the server. It gives users instant feedback and reduces unnecessary network requests.
  • Server-Side Validation — performed on the server after the data is sent. It is the authoritative check and cannot be bypassed by disabling JavaScript.

Both layers are necessary in production systems. Client-side validation improves user experience; server-side validation enforces security. Never rely on client-side validation alone.

sequenceDiagram
    participant User
    participant Browser
    participant Server

    User->>Browser: Fills out form and clicks Submit
    Browser->>Browser: Client-side validation (JS)
    alt Validation fails
        Browser-->>User: Show inline error messages
    else Validation passes
        Browser->>Server: POST form data
        Server->>Server: Server-side validation
        alt Server validation fails
            Server-->>Browser: Error response
            Browser-->>User: Show server error
        else All good
            Server-->>Browser: Success response
            Browser-->>User: Confirmation page
        end
    end

Chapter 2: Basic Form Validation

The class began with the most common scenario — a registration form that collects a name and an email address. The goals are simple: neither field can be empty, and the email must match a recognisable email pattern.

The HTML Form

The form uses onsubmit="return validateForm()". Returning false from validateForm() cancels the submission; returning true allows it to proceed. Each field is paired with an empty <span> whose job is to display error text in red.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Form Validation Example</title>
    <style>
        .error {
            color: red;
        }
    </style>
</head>
<body>
    <h1>User Registration</h1>
    <form id="registrationForm" onsubmit="return validateForm()">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name">
        <span id="nameError" class="error"></span>
        <br>
        <label for="email">Email:</label>
        <input type="text" id="email" name="email">
        <span id="emailError" class="error"></span>
        <br>
        <button type="submit">Register</button>
    </form>
    <script src="validation.js"></script>
</body>
</html>

validation.js

The script clears any previously displayed errors first (so stale messages from the last attempt don't accumulate), then reads the field values, and evaluates each rule in sequence. A single boolean flag isValid tracks whether every rule passed.

function validateForm() {
    // Clear previous error messages
    document.getElementById("nameError").textContent = "";
    document.getElementById("emailError").textContent = "";

    // Get form values
    let name = document.getElementById("name").value;
    let email = document.getElementById("email").value;

    let isValid = true;

    // Validate name
    if (name === "") {
        document.getElementById("nameError").textContent = "Name is required";
        isValid = false;
    }

    // Validate email
    if (email === "") {
        document.getElementById("emailError").textContent = "Email is required";
        isValid = false;
    } else if (!validateEmail(email)) {
        document.getElementById("emailError").textContent = "Invalid email format";
        isValid = false;
    }

    return isValid;
}

// Helper function to validate email format
function validateEmail(email) {
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailPattern.test(email);
}

How the email regex works:

SegmentMeaning
^Start of string
[^\s@]+One or more chars that are not whitespace or @ (the local part)
@The literal @ sign
[^\s@]+One or more chars (the domain name)
\.A literal dot
[^\s@]+$One or more chars after the dot (TLD), end of string

The pattern /^[^\s@]+@[^\s@]+\.[^\s@]+$/ is intentionally simple and pragmatic — it catches obvious typos without false-rejecting valid edge-case addresses.

Chapter 3: Advanced Validation

With basic validation in hand, the trainer pushed the class further. "Real registration forms need more: minimum password length, password confirmation, and phone number format." She unveiled the full advanced form.

The HTML Form

This form adds password, confirmPassword, and phone fields, each with its own error span and external script advancedValidation.js.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Advanced Form Validation Example</title>
    <style>
        .error {
            color: red;
        }
    </style>
</head>
<body>
    <h1>User Registration</h1>
    <form id="registrationForm" onsubmit="return validateForm()">
        <label for="name">Name:</label>
        <input type="text" id="name" name="name">
        <span id="nameError" class="error"></span>
        <br>
        <label for="email">Email:</label>
        <input type="text" id="email" name="email">
        <span id="emailError" class="error"></span>
        <br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password">
        <span id="passwordError" class="error"></span>
        <br>
        <label for="confirmPassword">Confirm Password:</label>
        <input type="password" id="confirmPassword" name="confirmPassword">
        <span id="confirmPasswordError" class="error"></span>
        <br>
        <label for="phone">Phone Number:</label>
        <input type="text" id="phone" name="phone">
        <span id="phoneError" class="error"></span>
        <br>
        <button type="submit">Register</button>
    </form>
    <script src="advancedValidation.js"></script>
</body>
</html>

advancedValidation.js

Five fields, five rule groups, two helper functions. Notice the password rules are evaluated in priority order: empty check first, then length check, then the confirm-match check on the second field.

function validateForm() {
    // Clear previous error messages
    document.getElementById("nameError").textContent = "";
    document.getElementById("emailError").textContent = "";
    document.getElementById("passwordError").textContent = "";
    document.getElementById("confirmPasswordError").textContent = "";
    document.getElementById("phoneError").textContent = "";

    // Get form values
    let name = document.getElementById("name").value;
    let email = document.getElementById("email").value;
    let password = document.getElementById("password").value;
    let confirmPassword = document.getElementById("confirmPassword").value;
    let phone = document.getElementById("phone").value;

    let isValid = true;

    // Validate name
    if (name === "") {
        document.getElementById("nameError").textContent = "Name is required";
        isValid = false;
    }

    // Validate email
    if (email === "") {
        document.getElementById("emailError").textContent = "Email is required";
        isValid = false;
    } else if (!validateEmail(email)) {
        document.getElementById("emailError").textContent = "Invalid email format";
        isValid = false;
    }

    // Validate password
    if (password === "") {
        document.getElementById("passwordError").textContent = "Password is required";
        isValid = false;
    } else if (password.length < 8) {
        document.getElementById("passwordError").textContent = "Password must be at least 8 characters";
        isValid = false;
    }

    // Validate confirm password
    if (confirmPassword === "") {
        document.getElementById("confirmPasswordError").textContent = "Confirm Password is required";
        isValid = false;
    } else if (password !== confirmPassword) {
        document.getElementById("confirmPasswordError").textContent = "Passwords do not match";
        isValid = false;
    }

    // Validate phone number
    if (phone === "") {
        document.getElementById("phoneError").textContent = "Phone number is required";
        isValid = false;
    } else if (!validatePhone(phone)) {
        document.getElementById("phoneError").textContent = "Invalid phone number format";
        isValid = false;
    }

    return isValid;
}

// Helper function to validate email format
function validateEmail(email) {
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailPattern.test(email);
}

// Helper function to validate phone number format
function validatePhone(phone) {
    const phonePattern = /^[0-9]{10}$/;
    return phonePattern.test(phone);
}

Key rules at a glance:

FieldRuleHow it's checked
NameNot emptyname === ""
EmailNot empty + valid formatvalidateEmail() with regex
PasswordNot empty + ≥ 8 characterspassword.length < 8
Confirm PasswordNot empty + matches passwordpassword !== confirmPassword
PhoneNot empty + exactly 10 digitsvalidatePhone() with /^[0-9]{10}$/

Phone regex breakdown: /^[0-9]{10}$/ matches a string that is exactly 10 consecutive decimal digits, nothing more. It rejects hyphens, spaces, and country-code prefixes — adjust the pattern if your application needs to accept those forms.

🧪 Try It Yourself

Task: Build the advanced registration form from Chapter 3 and deliberately trigger every error message.

  1. Save the HTML as registration.html and the JS as advancedValidation.js in the same folder.
  2. Open registration.html in your browser.
  3. Click Register with all fields empty — you should see five simultaneous error messages.
  4. Fill in a name, then enter notanemail in the email field — you should see "Invalid email format".
  5. Enter a 5-character password — you should see "Password must be at least 8 characters".
  6. Enter a valid password in the first field and a different string in the confirm field — you should see "Passwords do not match".
  7. Enter 12345 in the phone field — you should see "Invalid phone number format".

Starter snippet — use this as your advancedValidation.js starting point and fill in the missing validatePhone helper:

function validateForm() {
    document.getElementById("phoneError").textContent = "";
    let phone = document.getElementById("phone").value;
    let isValid = true;

    if (phone === "") {
        document.getElementById("phoneError").textContent = "Phone number is required";
        isValid = false;
    } else if (!validatePhone(phone)) {
        document.getElementById("phoneError").textContent = "Invalid phone number format";
        isValid = false;
    }

    return isValid;
}

function validatePhone(phone) {
    // TODO: write the regex that matches exactly 10 digits
}

Success criterion: After completing all seven steps above, every field should produce its specific error message — and when all fields are correctly filled, the form submits (or the page reloads) without any error messages appearing.

🔍 Checkpoint Quiz

Q1. Why should you never rely solely on client-side JavaScript validation to protect your application?

A) Because JavaScript runs too slowly to catch errors
B) Because users can disable JavaScript in their browser and bypass it entirely
C) Because server-side validation is slower and less accurate
D) Because regex patterns only work on the server

Q2. Given this snippet, what does it print to the console when email = "hello@" is passed in?

function validateEmail(email) {
    const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailPattern.test(email);
}
console.log(validateEmail("hello@"));

A) true
B) false
C) undefined
D) A syntax error is thrown

Q3. In advancedValidation.js, the confirm-password block only runs the "Passwords do not match" check inside an else if. What is the benefit of this structure compared to using a second independent if?

A) It runs faster because else if is a compiled keyword
B) It prevents showing "Passwords do not match" when the field is already flagged as empty
C) It makes the isValid flag reset itself automatically
D) There is no practical difference between else if and if here

Q4. You need to accept phone numbers in the format +91-9876543210 (country code + hyphen + 10 digits). The current pattern /^[0-9]{10}$/ rejects this. How would you update validatePhone to accept this format?

A1. B — JavaScript runs in the browser and a malicious or technically savvy user can disable it, open browser DevTools, or craft a raw HTTP request to send any data they choose directly to your server, bypassing all client-side checks.

A2. B — The string "hello@" has no characters after the @ and no dot-separated TLD, so the pattern /^[^\s@]+@[^\s@]+\.[^\s@]+$/ does not match and .test() returns false.

A3. B — If confirmPassword === "", the first branch sets the error to "Confirm Password is required" and sets isValid = false. The else if ensures the "Passwords do not match" message is only shown when the field actually has content — preventing two overlapping error messages on the same span.

A4. Update the regex to allow an optional country code and hyphen before the 10 digits: const phonePattern = /^(\+\d{1,3}-)?[0-9]{10}$/;. The group (\+\d{1,3}-)? makes the + sign, 1–3 digits, and hyphen optional, while the rest still enforces exactly 10 trailing digits.

🪞 Recap

  • Client-side validation runs in the browser and catches errors instantly; server-side validation is the authoritative layer that cannot be bypassed.
  • The pattern onsubmit="return validateForm()" lets a JavaScript function cancel form submission by returning false.
  • Clearing error spans at the start of every validateForm() call prevents stale messages from lingering across submission attempts.
  • The email regex /^[^\s@]+@[^\s@]+\.[^\s@]+$/ and phone regex /^[0-9]{10}$/ are concise, pragmatic patterns for common format checks.
  • Password rules should be evaluated in priority order: empty → too short → confirm mismatch — so each field shows only the most relevant error at a time.

📚 Further Reading

Like this topic? It’s one of 48 in Full Stack Essentials.

Block your seat for ₹2,500 and join the next cohort.