Built-in Validation
HTML5 provides built-in validation that works without JavaScript.
Validation Attributes
<!-- Required field -->
<input type="text" required>
<!-- Email format -->
<input type="email" required>
<!-- Validates: user@example.com -->
<!-- URL format -->
<input type="url" required>
<!-- Validates: https://example.com -->
<!-- Number range -->
<input type="number" min="0" max="100" step="1">
<!-- Length constraints -->
<input type="text" minlength="3" maxlength="20">
<!-- Pattern matching -->
<input type="text" pattern="[A-Za-z]{3}">
Validation States
const input = document.querySelector('input');
// Check validity
input.checkValidity(); // true or false
// Get validation message
input.validationMessage; // "Please fill out this field"
// Validity state object
input.validity.valueMissing; // required but empty
input.validity.typeMismatch; // wrong format (email, url)
input.validity.tooShort; // below minlength
input.validity.tooLong; // above maxlength
input.validity.rangeUnderflow; // below min
input.validity.rangeOverflow; // above max
input.validity.stepMismatch; // wrong step value
input.validity.patternMismatch; // doesn't match pattern
input.validity.valid; // all checks passed
Styling Validation States
/* Valid input */
input:valid {
border-color: green;
background-color: #f0fff0;
}
/* Invalid input */
input:invalid {
border-color: red;
background-color: #fff0f0;
}
/* Required field */
input:required {
border-left: 3px solid orange;
}
/* Focus state */
input:focus:invalid {
box-shadow: 0 0 5px rgba(255, 0, 0, 0.5);
}
Disabling Validation
<!-- Disable for entire form -->
<form novalidate>
<input type="email" required>
<button type="submit">Submit</button>
</form>
<!-- Disable for specific button -->
<button type="submit" formnovalidate>Save Draft</button>
Custom Validation Messages
const input = document.querySelector('input');
input.addEventListener('invalid', (e) => {
e.preventDefault(); // Prevent default browser message
if (input.validity.valueMissing) {
input.setCustomValidity('Please enter your email');
} else if (input.validity.typeMismatch) {
input.setCustomValidity('Please enter a valid email address');
} else {
input.setCustomValidity(''); // Clear custom message
}
});
// Reset on input
input.addEventListener('input', () => {
input.setCustomValidity('');
});
Pattern Matching
The pattern attribute lets you validate input using regular expressions.
Common Patterns
<!-- Phone number (US) -->
<input type="tel" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}">
<!-- Format: 123-456-7890 -->
<!-- Alphanumeric -->
<input type="text" pattern="[A-Za-z0-9]+">
<!-- Letters only -->
<input type="text" pattern="[A-Za-z]+">
<!-- Capital letters -->
<input type="text" pattern="[A-Z]+">
<!-- At least 3 characters -->
<input type="text" pattern=".{3,}">
<!-- Credit card (basic) -->
<input type="text" pattern="[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}">
<!-- Format: 1234-5678-9012-3456 -->
<!-- Social Security Number -->
<input type="text" pattern="[0-9]{3}-[0-9]{2}-[0-9]{4}">
<!-- Format: 123-45-6789 -->
<!-- ZIP code (US) -->
<input type="text" pattern="[0-9]{5}(-[0-9]{4})?">
<!-- Format: 12345 or 12345-6789 -->
Pattern Syntax
. → Any character (except newline)
\\d → Digit [0-9]
\\w → Word character [A-Za-z0-9_]
\\s → Whitespace
[A-Z] → Uppercase letter
[a-z] → Lowercase letter
[0-9] → Digit
[^abc] → Not a, b, or c
* → 0 or more
+ → 1 or more
? → 0 or 1
{n} → Exactly n
{n,} → n or more
{n,m} → Between n and m
^ → Start of string
$ → End of string
(abc) → Group
a|b → a or b
Real-World Examples
<!-- Username (3-20 chars, alphanumeric) -->
<input type="text" pattern="^[a-zA-Z0-9]{3,20}$">
<!-- Password (min 8 chars, 1 uppercase, 1 number) -->
<input type="password" pattern="^(?=.*[A-Z])(?=.*[0-9]).{8,}$">
<!-- Date (MM/DD/YYYY) -->
<input type="text" pattern="^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/[0-9]{4}$">
<!-- Hex color -->
<input type="text" pattern="^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$">
<!-- ISBN-13 -->
<input type="text" pattern="^97[89]-[0-9]-[0-9]{4}-[0-9]{4}-[0-9]$">
Pattern Validation with JavaScript
const input = document.querySelector('input[pattern]');
const pattern = new RegExp(input.pattern);
input.addEventListener('input', () => {
if (input.value && !pattern.test(input.value)) {
input.setCustomValidity('Invalid format');
} else {
input.setCustomValidity('');
}
});
Custom Validation
For complex validation rules, use JavaScript with the Constraint Validation API.
Constraint Validation API
const form = document.querySelector('form');
const email = document.querySelector('input[type="email"]');
// Check validity
email.checkValidity(); // true or false
// Get message
email.validationMessage; // "Please fill out this field"
// Validity object
email.validity = {
valueMissing: false,
typeMismatch: false,
tooShort: false,
tooLong: false,
rangeUnderflow: false,
rangeOverflow: false,
stepMismatch: false,
patternMismatch: false,
customError: false,
valid: true
};
// Set custom error
email.setCustomValidity('Email already exists');
// Reset custom error
email.setCustomValidity('');
Form Submit Handler
form.addEventListener('submit', (e) => {
// Prevent default validation
e.preventDefault();
// Custom validation
let isValid = true;
// Validate each field
document.querySelectorAll('input[required]').forEach(input => {
if (!input.value.trim()) {
showError(input, 'This field is required');
isValid = false;
} else {
clearError(input);
}
});
// Validate email format
const email = document.querySelector('input[type="email"]');
if (email.value && !isValidEmail(email.value)) {
showError(email, 'Please enter a valid email');
isValid = false;
}
// Validate password strength
const password = document.querySelector('input[type="password"]');
if (password.value && !isStrongPassword(password.value)) {
showError(password, 'Password must be at least 8 characters with uppercase and number');
isValid = false;
}
if (isValid) {
form.submit();
}
});
// Helper functions
function isValidEmail(email) {
return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);
}
function isStrongPassword(password) {
return /^(?=.*[A-Z])(?=.*[0-9]).{8,}$/.test(password);
}
function showError(input, message) {
const error = input.nextElementSibling;
if (error && error.classList.contains('error')) {
error.textContent = message;
} else {
const div = document.createElement('div');
div.className = 'error';
div.textContent = message;
input.parentNode.insertBefore(div, input.nextSibling);
}
input.classList.add('invalid');
}
function clearError(input) {
const error = input.nextElementSibling;
if (error && error.classList.contains('error')) {
error.remove();
}
input.classList.remove('invalid');
}
Real-Time Validation
// Validate on input (real-time feedback)
document.querySelectorAll('input').forEach(input => {
input.addEventListener('input', () => {
if (input.checkValidity()) {
input.classList.remove('invalid');
input.classList.add('valid');
} else {
input.classList.remove('valid');
input.classList.add('invalid');
}
});
});
Server-Side Validation
// Always validate on server too!
app.post('/api/users', (req, res) => {
const { email, password } = req.body;
// Server-side validation
if (!email || !isValidEmail(email)) {
return res.status(400).json({ error: 'Invalid email' });
}
if (!password || password.length < 8) {
return res.status(400).json({ error: 'Password too short' });
}
// Process valid data
createUser({ email, password });
res.json({ success: true });
});
Practice Problems
Create a reusable React component implementing Form Validation. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Form Validation using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Form Validation for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What does the required attribute do?
2. What is the pattern attribute used for?
3. Why should you always validate on the server?
4. What does setCustomValidity() do?
Flashcards
Question
What is HTML5 form validation?
Click to reveal answer
Answer
Built-in validation using attributes like required, pattern, min/max, minlength/maxlength. Works without JavaScript.
Question
What is the Constraint Validation API?
Click to reveal answer
Answer
JavaScript API for custom validation: checkValidity(), setCustomValidity(), validity object, validationMessage.
Question
Why is client-side validation not enough?
Click to reveal answer
Answer
It can be bypassed by disabling JavaScript or using tools. Always validate on the server too.
Question
What is Form Validation?
Click to reveal answer
Answer
Form Validation is a key concept in frontend development.
Question
When to use Form Validation?
Click to reveal answer
Answer
Use Form Validation when building production systems that require reliability, scalability, and maintainability.
Revision Notes
Key Takeaways
- 1.HTML5 provides built-in validation with no JavaScript needed
- 2.Use pattern attribute for regex-based validation
- 3.Always validate on the server - client-side can be bypassed
- 4.Provide clear, helpful error messages
- 5.Use the Constraint Validation API for complex rules
Interview Tips
- •Know the difference between client-side and server-side validation
- •Understand the Constraint Validation API
- •Be able to write validation patterns for common formats
- •Know why server-side validation is essential
Cheat Sheet
Form Validation Cheat Sheet
Built-in Attributes:
- required: Must be filled
- type="email"/"url": Format validation
- min/max: Number range
- minlength/maxlength: Text length
- pattern: Regex validation
Constraint Validation API:
- checkValidity(): Returns boolean
- validationMessage: Error message
- setCustomValidity(): Set custom error
- validity: Object with error states
Styling:
- :valid - Valid input
- :invalid - Invalid input
- :required - Required field
Best Practices:
- Always validate on server too
- Provide clear error messages
- Validate in real-time
- Handle edge cases