100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
JavaScript

Form Validation in JavaScript

Learn to validate form input using built-in HTML5 constraint validation attributes and custom JavaScript logic.

DOM & EventsIntermediate10 min readJul 8, 2026
Analogies

1. Introduction

Form validation ensures that user-submitted data meets expected rules (required fields, correct format, value ranges) before it is processed or sent to a server. There are two complementary approaches: declarative HTML5 constraint validation attributes, and imperative JavaScript validation logic for cases the built-in attributes cannot express.

🏏

Cricket analogy: Just as a match referee checks a bowler's run-up is within the marked crease (declarative rule set by the pitch) and also manually reviews a suspicious bowling action frame-by-frame (imperative judgment), form validation combines built-in HTML5 rules with custom JS checks before data is submitted.

Client-side validation improves user experience with immediate feedback, but it is never a substitute for server-side validation, since client-side checks can always be bypassed.

🏏

Cricket analogy: A batter shadow-practicing their shot at the crease before facing a real ball gives instant feedback, but the umpire's actual decision at the wicket is the real check -- client-side validation is like the shadow practice, never a substitute for server-side enforcement.

2. Syntax

html
<form id="signupForm" novalidate>
  <input type="email" name="email" required placeholder="Email">
  <input type="password" name="password" minlength="8" required placeholder="Password">
  <input type="number" name="age" min="18" max="120">
  <input type="text" name="username" pattern="[A-Za-z0-9_]{3,16}" required>
  <button type="submit">Sign up</button>
</form>
javascript
const form = document.getElementById('signupForm');
const email = form.elements.email;

// HTML5 built-in validation API
console.log(email.validity.valid);       // boolean
console.log(email.validity.valueMissing); // true if required & empty
console.log(email.checkValidity());       // triggers validity check, returns boolean

// Custom JS validation on submit
form.addEventListener('submit', (event) => {
  event.preventDefault(); // stop native submission/reload while we validate

  if (!form.checkValidity()) {
    form.reportValidity(); // show native error bubbles
    return;
  }
  const password = form.elements.password.value;
  if (password.toLowerCase() === password) {
    email.setCustomValidity('Password must contain an uppercase letter');
    form.reportValidity();
    return;
  }
  email.setCustomValidity(''); // clear any previous custom error
  console.log('Form is valid, submitting via fetch...');
});

3. Explanation

HTML5 provides declarative constraint validation attributes such as required, minlength/maxlength, min/max, pattern, and input type (email, number, url, etc.). Browsers automatically enforce these when a form is submitted (unless novalidate is set on the <form>), showing native tooltip-style error messages and blocking submission.

🏏

Cricket analogy: HTML5's 'required' attribute is like a mandatory toss-coin rule that must happen before play begins, 'pattern' is like enforcing a legal bowling action shape, and browsers automatically block the 'match start' (submission) with a native warning tooltip unless the umpire waives the rule (novalidate).

JavaScript validation is needed for rules HTML5 attributes cannot express — cross-field comparisons (password confirmation matching), business logic (username availability via an API call), or custom messaging. The Constraint Validation API (element.validity, checkValidity(), reportValidity(), setCustomValidity()) lets JavaScript hook into and extend the native validation system rather than reimplementing it from scratch.

🏏

Cricket analogy: Checking that a bowler's declared pace matches their actual delivery speed on the radar gun (cross-field comparison) or verifying team-roster eligibility via a league database call (API business logic) needs custom JS, using setCustomValidity() like a referee adding a custom ruling note beyond the standard rulebook.

A common pattern is to call event.preventDefault() in the submit handler to stop the native page-reload submission, run checkValidity(), and only proceed (e.g., with a fetch call) if valid; native and custom validity messages can both be surfaced via reportValidity().

🏏

Cricket analogy: Just as an umpire holds up play with a raised hand (preventDefault) before checking all fielding positions are legal (checkValidity), and only signals play (proceeds with the fetch-equivalent next ball) if everything passes, announcing any issue over the PA (reportValidity).

Gotcha: Client-side validation (HTML5 attributes or JavaScript) is purely for user experience — it can be trivially bypassed by disabling JavaScript, editing DOM attributes in DevTools, or sending requests directly to the API. Server-side validation of all incoming data is mandatory for security and data integrity; never trust client-side checks alone.

4. Example

html
<form id="loginForm">
  <input type="email" id="email" required>
  <input type="password" id="pwd" minlength="8" required>
  <span id="error"></span>
  <button type="submit">Login</button>
</form>
javascript
const form = document.getElementById('loginForm');
const errorSpan = document.getElementById('error');

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

  const emailInput = document.getElementById('email');
  const pwdInput = document.getElementById('pwd');

  if (!emailInput.validity.valid) {
    errorSpan.textContent = 'Please enter a valid email address.';
    return;
  }
  if (pwdInput.value.length < 8) {
    errorSpan.textContent = 'Password must be at least 8 characters.';
    return;
  }
  console.log('Validated -- submitting login for', emailInput.value);
});

// Simulate: user types "bademail" and password "123" then submits
emailInput.value = 'bademail';
pwdInput.value = '123';

5. Output

text
On submit with email = 'bademail', password = '123':

1. e.preventDefault() stops the native page reload.
2. emailInput.validity.valid is false (type="email" requires an '@' and domain).
3. errorSpan text content becomes:
   "Please enter a valid email address."
4. console.log('Validated -- submitting...') does NOT run.

If corrected to email = 'user@example.com', password = '123' (7 chars, too short):
errorSpan text becomes:
   "Password must be at least 8 characters."

Only when both checks pass does the console print:
   "Validated -- submitting login for user@example.com"

6. Key Takeaways

  • HTML5 attributes (required, pattern, min/max, minlength/maxlength, type) provide declarative validation for free.
  • The Constraint Validation API (validity, checkValidity(), reportValidity(), setCustomValidity()) extends native validation from JS.
  • event.preventDefault() in a submit handler stops the native page reload so custom JS validation/AJAX can run.
  • Use JS validation for cross-field rules and business logic HTML5 attributes cannot express.
  • Client-side validation is a UX convenience only — server-side validation is always required for security.

Practice what you learned

Was this page helpful?

Topics covered

#JavaScript#JavaScriptProgrammingStudyNotes#Programming#FormValidationInJavaScript#Form#Validation#Syntax#Explanation#StudyNotes#SkillVeris