Lesson 1, Topic 1
In Progress

Lesson 3.10: JavaScript Form Validation

Lesson 3.10 – JavaScript Form Validation | Knowledge Pillars HCCS
Unit 3 · Lesson 3.10

JavaScript Form Validation

Stop bad data before it ever leaves the page. Learn how JavaScript checks your contact form — blocking empty fields, catching invalid emails, and giving users instant, helpful feedback.

HTML & CSS Web Design ~55 Minutes Intermediate

Lesson Objectives

  • Explain what client-side form validation is and why it improves user experience
  • Read form field values using element.value and clean them with .trim()
  • Use addEventListener('submit', ...) and event.preventDefault() to intercept form submission
  • Write a validation function that checks for empty fields and a valid email format
  • Display inline error messages using DOM manipulation rather than blocking alert() dialogs
  • Show a success message when all fields pass validation

Part 1: Why Validate Forms?

Your contact form (built in Lesson 3.2) can currently be submitted completely empty — or with a fake email address like notanemail. That's a problem. Form validation catches these issues before data goes anywhere, giving users instant, friendly feedback so they can fix the problem right away.

Without validation, users can submit:

  • ❌ A completely blank name field
  • ❌ A missing or malformed email address (e.g., hello with no @)
  • ❌ An empty message box

Two Layers of Validation

HTML5 vs JavaScript Validation
Type How It Works What It Can Do Limitation
HTML5 Built-in required, type="email" attributes on inputs Blocks empty required fields; checks basic email format Browser tooltips only — no custom messages or styling
JavaScript Custom A function that runs when the form is submitted Custom error messages, field highlighting, success feedback, complex rules Can be bypassed if JavaScript is disabled
💡 Use Both! Keep the required attribute and type="email" on your inputs and add JavaScript validation. HTML5 provides a baseline safety net; JavaScript provides the polished, user-friendly experience. Never rely on client-side validation alone for security — a real server should always validate too.

Part 2: How Validation Works

When a user clicks Submit, JavaScript intercepts the event, reads each field's value, runs checks, and either shows an error or allows the form to proceed. Here is the logic as a flow:

Key JavaScript Techniques Used

// 1. Read a field's value let name = document.getElementById('name').value; // 2. .trim() removes leading and trailing whitespace // so " " (spaces only) is treated as empty, not valid let name = document.getElementById('name').value.trim(); // 3. Check if a field is empty if (name === '') { /* show error */ } // 4. Check if email contains "@" if (!email.includes('@')) { /* show error */ } // 5. Intercept form submission — stop the default page reload form.addEventListener('submit', function(event) { event.preventDefault(); // stop the form from sending immediately // ... run validation checks here ... });

Part 3: The Complete Validation Function

Here is the full validation pattern — from the HTML form update to the complete JavaScript function. Study each part and its comment carefully before implementing it on your own site.

Step 1 — Update the HTML Form

Make sure your form has id="contactForm" and your fields have matching IDs. We give the error message elements their own <span> tags so JavaScript can write into them:

<form id="contactForm" action="#" method="POST" novalidate> <label for="name">Your Name:</label> <input type="text" id="name" name="name" placeholder="Jane Smith"> <span id="name-error" class="error-msg" aria-live="polite"></span> <label for="email">Your Email:</label> <input type="email" id="email" name="email" placeholder="jane@example.com"> <span id="email-error" class="error-msg" aria-live="polite"></span> <label for="message">Your Message:</label> <textarea id="message" name="message" rows="5"></textarea> <span id="message-error" class="error-msg" aria-live="polite"></span> <button type="submit">Send Message</button> <p id="form-success"></p> </form>
💡 What is novalidate? Adding novalidate to the <form> tag turns off the browser's built-in HTML5 validation popups. This lets your JavaScript show its own custom inline error messages instead — giving you full control over the user experience.

Step 2 — The CSS for Error & Success States

/* In style.css */ .error-msg { display: block; color: #b91c1c; font-size: .85rem; font-weight: 700; min-height: 20px; margin-bottom: 8px; } input.error, textarea.error { border: 2px solid #b91c1c; background-color: #fff5f5; } input.success, textarea.success { border: 2px solid #16a34a; background-color: #f0fdf4; } #form-success { color: #14532d; font-weight: 700; margin-top: 10px; }

Step 3 — The JavaScript Validation Function

<script> let form = document.getElementById('contactForm'); form.addEventListener('submit', function(event) { event.preventDefault(); // stop default form submission let name = document.getElementById('name').value.trim(); let email = document.getElementById('email').value.trim(); let message = document.getElementById('message').value.trim(); ['name', 'email', 'message'].forEach(function(id) { document.getElementById(id).classList.remove('error', 'success'); document.getElementById(id + '-error').textContent = ''; }); document.getElementById('form-success').textContent = ''; let valid = true; if (name === '') { document.getElementById('name-error').textContent = 'Name is required.'; document.getElementById('name').classList.add('error'); valid = false; } else { document.getElementById('name').classList.add('success'); } if (email === '') { document.getElementById('email-error').textContent = 'Email is required.'; document.getElementById('email').classList.add('error'); valid = false; } else if (!email.includes('@')) { document.getElementById('email-error').textContent = 'Please enter a valid email address.'; document.getElementById('email').classList.add('error'); valid = false; } else { document.getElementById('email').classList.add('success'); } if (message === '') { document.getElementById('message-error').textContent = 'Message cannot be empty.'; document.getElementById('message').classList.add('error'); valid = false; } else { document.getElementById('message').classList.add('success'); } if (valid) { document.getElementById('form-success').textContent = '✅ Thank you! Your message has been sent.'; form.reset(); ['name', 'email', 'message'].forEach(function(id) { document.getElementById(id).classList.remove('success'); }); } }); </script>
⚠️ Never trust only client-side validation. JavaScript can be disabled by the user, and crafted requests can bypass it entirely. Client-side validation is for user experience — fast, helpful feedback. Real applications always validate again on the server before accepting or storing data.

Part 4: See It in Action

This is a fully working validated form. Try submitting it with various combinations of empty and filled fields to see the inline error messages and success state in action.

🔍 Live Demo — Validated Contact Form

Try submitting empty, with a bad email, or fully filled out. Watch the inline error messages and green success state appear.

Student Activity

🛠️ Validate It

Make Your Form Smarter with JavaScript Validation

Title: Make Your Form Smarter with JavaScript Validation  |  Platform: Knowledge Pillars Coding Lab

You built your contact form in Lesson 3.2 and gave it id="contactForm". Now add JavaScript that intercepts submission, checks every field, shows inline errors, and confirms success — without ever blocking the page with an alert().

  1. Add novalidate and error spans to your form in index.html. Update your existing form tag and add an error <span> after each input and a success paragraph at the end:
    <!-- Update your <form> tag --> <form id="contactForm" action="#" method="POST" novalidate> <!-- After your name input --> <span id="name-error" class="error-msg" aria-live="polite"></span> <!-- After your email input --> <span id="email-error" class="error-msg" aria-live="polite"></span> <!-- After your textarea --> <span id="message-error" class="error-msg" aria-live="polite"></span> <!-- Success message — after your submit button --> <p id="form-success"></p> </form>

    💾 Save index.html.

  2. Add the error styling to style.css.
    .error-msg { display: block; color: #b91c1c; font-size: .85rem; font-weight: 700; min-height: 20px; margin-bottom: 8px; } input.error, textarea.error { border: 2px solid #b91c1c; background-color: #fff5f5; } input.success, textarea.success { border: 2px solid #16a34a; background-color: #f0fdf4; } #form-success { color: #14532d; font-weight: 700; margin-top: 10px; }

    💾 Save style.css.

  3. Add the validation script just before </body> in index.html. Add this inside your existing <script> block (or a new one):
    let form = document.getElementById('contactForm'); form.addEventListener('submit', function(event) { event.preventDefault(); let name = document.getElementById('name').value.trim(); let email = document.getElementById('email').value.trim(); let message = document.getElementById('message').value.trim(); let valid = true; ['name', 'email', 'message'].forEach(function(id) { document.getElementById(id).classList.remove('error', 'success'); document.getElementById(id + '-error').textContent = ''; }); document.getElementById('form-success').textContent = ''; if (name === '') { document.getElementById('name-error').textContent = 'Name is required.'; document.getElementById('name').classList.add('error'); valid = false; } else { document.getElementById('name').classList.add('success'); } if (email === '') { document.getElementById('email-error').textContent = 'Email is required.'; document.getElementById('email').classList.add('error'); valid = false; } else if (!email.includes('@')) { document.getElementById('email-error').textContent = 'Please enter a valid email address.'; document.getElementById('email').classList.add('error'); valid = false; } else { document.getElementById('email').classList.add('success'); } if (message === '') { document.getElementById('message-error').textContent = 'Message cannot be empty.'; document.getElementById('message').classList.add('error'); valid = false; } else { document.getElementById('message').classList.add('success'); } if (valid) { document.getElementById('form-success').textContent = '✅ Thank you! Your message has been sent.'; form.reset(); } });

    💾 Save both files and test your form thoroughly — try all the error combinations!

🌟 Bonus Challenges

Check minimum message length (at least 10 characters):

if (message.length < 10) { document.getElementById('message-error').textContent = 'Message must be at least 10 characters.'; document.getElementById('message').classList.add('error'); valid = false; }

Live character counter for the message field:

<!-- In HTML, below the textarea --> <small id="char-count">0 characters</small> // In <script> document.getElementById('message') .addEventListener('input', function() { document.getElementById('char-count').textContent = this.value.length + ' characters'; });

Vocabulary

Form Validation
Checking form field values before submission to ensure they are present and correctly formatted
Client-side Validation
Validation that runs in the browser using JavaScript — provides instant feedback without a server round-trip
event.preventDefault()
Stops the browser's default action — used here to stop form submission so JavaScript can run checks first
.value
A property of form inputs — returns what the user has typed into the field as a string
.trim()
Removes whitespace from the start and end of a string — prevents spaces-only from passing as valid input
.includes('@')
Returns true if the string contains the given substring — used here to check for a valid email format
novalidate
An HTML form attribute that disables the browser's default validation popups — letting JavaScript handle all feedback instead
form.reset()
A JavaScript method that clears all fields in a form — called after successful validation to give users a fresh start

Lesson Summary

Lesson 3.10 — Key Concepts
Concept / MethodWhat It Does
novalidate on <form>Disables browser HTML5 validation popups — hands full control to your JavaScript
addEventListener('submit', fn)Listens for the form's submit event — fires the validation function before anything is sent
event.preventDefault()Stops the default form submission — keeps the user on the page while validation runs
element.value.trim()Reads the field's value and strips leading/trailing whitespace
if (name === '')Checks whether a field is empty — the core empty-field validation
!email.includes('@')Returns true if the email is missing an @ symbol — basic email format check
Inline error messages via textContentWrites error text directly into a <span> next to the field — no alert() needed
classList.add('error')Adds a red-border CSS class to the failing field for clear visual feedback
classList.add('success')Adds a green-border class when a field passes validation
form.reset()Clears all fields after successful submission
Client-side onlyAlways validate on the server too — client-side validation improves UX but is not a security measure

Knowledge Check

Read each question carefully and select the best answer. Each question has one correct response.

1. What does event.preventDefault() do inside a form's submit handler?

2. Why is .trim() used when reading form field values?

3. What does !email.includes('@') check?

4. What is the purpose of adding novalidate to the <form> tag?

5. Why is client-side JavaScript validation alone not enough for a real production website?

Activity Checklist

  • I added novalidate to my <form> tag
  • I added <span class="error-msg"> elements after each input field with matching IDs
  • I added a <p id="form-success"> element after the submit button
  • I added .error-msg, input.error, input.success CSS rules to style.css
  • I used addEventListener('submit', ...) to attach my validation function
  • I called event.preventDefault() at the start of the handler
  • I used .value.trim() to read and clean each field's value
  • I check for empty name, empty/invalid email, and empty message — setting valid = false on any failure
  • Errors are shown via textContent in the span elements and classList.add('error') on the fields
  • On success I show a confirmation message and call form.reset()
  • I tested all error scenarios: empty submit, bad email, partial fill, and fully valid submission
  • I saved both files and committed my changes in the Knowledge Pillars Coding Lab

🎉 You've Completed Unit 3!

You've built a fully featured personal website using HTML structure, CSS styling and animations, responsive Flexbox & Grid layouts, embedded media and maps, and interactive JavaScript. You're ready for the Unit 3 Final Project!