Topic 6: JavaScript Validation
📖 8 min read · 🎯 Intermediate · 🧭 Prerequisites: css-advance, div-page-design
Why this matters
Picture this: you build a beautiful sign-up form — clean design, perfect layout — and someone types "aaaaaa" into the email field, leaves the phone number blank, and hits Submit. That bad data just sailed straight into your database. Now you have a mess to clean up, and your users never even got a warning. That's exactly the problem JavaScript validation solves. It catches bad input right there in the browser, the moment it happens, before anything gets sent to a server. In this lesson, you'll learn how to write those checks yourself.
What You'll Learn
- The difference between client-side and server-side validation, and when each applies
- How to write a
validateForm()function that blocks form submission on invalid input - How to use regular expressions to validate email addresses and phone numbers
- How to extend basic validation to cover password strength and password-match checks
The Analogy
Think of JavaScript validation like the front-desk receptionist at a government office. Before your paperwork ever reaches the clerk in the back room, the receptionist checks: Did you fill in your name? Is that actually a date of birth, or just random numbers? Are both signatures present? Catching those mistakes at the front desk is infinitely cheaper than discovering them after the clerk has spent an hour processing the form — or worse, after the wrong data has already been filed. Client-side validation is that receptionist: fast, immediate, and user-friendly. Server-side validation is the senior clerk who double-checks everything anyway — because the receptionist can be bypassed.
Chapter 1: The Importance of Validation
Validation is the process of ensuring that data entered by a user meets specific criteria before it is processed. Without it, your application risks storing garbage data, triggering server errors, or opening the door to security vulnerabilities.
Validation comes in two flavors:
- Client-Side Validation — performed in the browser before data is sent to the server. It gives users instant feedback and reduces unnecessary network requests.
- Server-Side Validation — performed on the server after data is sent. It is the authoritative safety net and should always exist, because client-side checks can be bypassed by anyone with browser dev tools.
The two types are complementary, not interchangeable. A production application needs both. In this lesson we focus on client-side validation using JavaScript.
Chapter 2: Basic Form Validation
The class started with a registration form that collects a user's name and email. The goal: ensure both fields are filled out and that the email follows a recognizable format.
The HTML Form
<!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>
A few things to notice:
onsubmit="return validateForm()"— when the form tries to submit,validateForm()runs. If it returnsfalse, the submission is cancelled.- Each input has a sibling
<span>with anidending inErrorand the classerror. JavaScript will write messages into these spans. - The CSS rule
.error { color: red; }makes those messages visible.
The JavaScript — validation.js
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);
}
Breaking it down:
- Clear old errors first. Every time the user hits submit, stale messages are wiped before new ones are written. Otherwise a fixed mistake might still show an old error.
- Read values from the DOM.
document.getElementById("name").valuegrabs whatever the user typed. isValidflag. Starts astrue; flips tofalsewhen any check fails. The function returns this flag —falseprevents submission.validateEmail(email)uses a regular expression:/^[^\s@]+@[^\s@]+\.[^\s@]+$/. This pattern requires at least one non-whitespace, non-@character before the@, at least one after, a literal., and at least one character following the dot.
flowchart TD
A[User clicks Submit] --> B{name === empty?}
B -- Yes --> C[Show nameError · isValid = false]
B -- No --> D{email === empty?}
C --> D
D -- Yes --> E[Show emailError · isValid = false]
D -- No --> F{validateEmail passes?}
E --> G[return isValid]
F -- No --> H[Show invalid format · isValid = false]
F -- Yes --> G
H --> G
G -- false --> I[Form blocked]
G -- true --> J[Form submits]
Chapter 3: Advanced Validation
the trainer leaned forward. "A name and an email are a good start — but what about passwords? Phone numbers? Length requirements?" The class extended the form to cover four additional scenarios: password presence, password length, password confirmation match, and phone number format.
The Extended HTML Form
<!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>
The JavaScript — advancedValidation.js
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);
}
What's new here:
| Rule | Check | Error message |
|---|---|---|
| Password presence | password === "" | "Password is required" |
| Password length | password.length < 8 | "Password must be at least 8 characters" |
| Password match | password !== confirmPassword | "Passwords do not match" |
| Phone presence | phone === "" | "Phone number is required" |
| Phone format | validatePhone(phone) fails | "Invalid phone number format" |
validatePhone uses the pattern /^[0-9]{10}$/ — exactly 10 digits, nothing else. Adjust the {10} to match your region's number length, or expand the pattern to support country codes and dashes.
Why check both presence AND format? The else if structure means: if the field is empty, show the "required" message and stop; only if it's not empty do we bother checking the format. This prevents two error messages appearing for the same field at once.
🧪 Try It Yourself
Task: Build the advanced registration form locally and deliberately break it.
- Create two files —
index.htmlandadvancedValidation.js— using the code from Chapter 3 above. - Open
index.htmlin your browser. - Click Register without filling anything in. You should see five red error messages simultaneously.
- Fill in a valid name and email, then type a 5-character password. Click Register. You should see: "Password must be at least 8 characters".
- Fill in a valid password, then type a different string in Confirm Password. You should see: "Passwords do not match".
- Enter
12345in the phone field. You should see: "Invalid phone number format" (only 5 digits; the pattern requires exactly 10).
Success criterion: All five fields pass simultaneously — no red text — and the browser either navigates away or (if there's no server) the form simply resets. Open the browser console; there should be no JavaScript errors.
Starter snippet — modify validatePhone to accept dashes:
function validatePhone(phone) {
// Accepts formats: 1234567890 or 123-456-7890
const phonePattern = /^[0-9]{3}-?[0-9]{3}-?[0-9]{4}$/;
return phonePattern.test(phone);
}
🔍 Checkpoint Quiz
Q1. What is the key difference between client-side validation and server-side validation, and why do production applications need both?
Q2. Given this snippet, what does it print to the console when email = "hello@world" is passed?
function validateEmail(email) {
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailPattern.test(email);
}
console.log(validateEmail("hello@world"));
A) true
B) false
C) undefined
D) It throws a TypeError
Q3. What is the bug in the following password validation block?
if (password.length < 8) {
document.getElementById("passwordError").textContent = "Password must be at least 8 characters";
isValid = false;
}
if (confirmPassword !== password) {
document.getElementById("confirmPasswordError").textContent = "Passwords do not match";
isValid = false;
}
A) password.length should be password.size
B) An empty password field would skip the length check entirely and show no error
C) The confirm password check runs even when confirmPassword is empty, potentially showing a confusing mismatch error instead of a "required" message
D) isValid cannot be set inside an if block
Q4. You are building a sign-up form for a Vizag event. A user's age must be between 18 and 99 (inclusive). Write a short JavaScript if block that validates the age variable and sets an appropriate message on document.getElementById("ageError").
A1. Client-side validation runs in the browser and gives instant feedback without a network round-trip — but it can be bypassed by disabling JavaScript or crafting manual HTTP requests. Server-side validation is authoritative and cannot be bypassed by the client. Production apps need both: client-side for UX speed, server-side for actual data integrity and security.
A2. B) false — The pattern requires at least one character after the final . (the [^\s@]+ after the last \.). "hello@world" has no dot after world, so the regex fails to match and .test() returns false.
A3. C) — Because there is no if (confirmPassword === "") { ... } guard before the mismatch check, an empty confirm-password field will always trigger "Passwords do not match" instead of "Confirm Password is required". The fix is to check for emptiness first with an else if chain, as shown in advancedValidation.js.
A4.
let age = parseInt(document.getElementById("age").value, 10);
if (isNaN(age) || age < 18 || age > 99) {
document.getElementById("ageError").textContent = "Age must be between 18 and 99";
isValid = false;
}
isNaN covers the case where the field is empty or non-numeric; the range check covers out-of-bounds values.
🪞 Recap
- Client-side validation catches bad data in the browser instantly; server-side validation is the authoritative backstop — you need both.
- A
validateForm()function tied toonsubmit="return validateForm()"blocks form submission by returningfalsewhen any check fails. - Always clear previous error messages at the top of
validateForm()before running new checks. - Regular expressions —
/^[^\s@]+@[^\s@]+\.[^\s@]+$/for email,/^[0-9]{10}$/for a 10-digit phone — let you enforce format rules in a single line. - Use
else ifchains for each field so only one error message appears per field at a time, and length/format checks don't run on empty strings.
📚 Further Reading
- MDN — Client-side form validation — the source of truth on HTML5 constraint validation and the Constraint Validation API
- MDN — Regular Expressions — a complete guide to writing and reading regex patterns in JavaScript
- HTML Living Standard — The
constraint validationAPI — spec-level detail oncheckValidity(),setCustomValidity(), and built-in browser validation hooks - ⬅️ Previous: Div Page Design
- ➡️ Next: JavaScript Cookies