Advanced Form Validation
Form validation ensures that the data submitted by users matches the expected format.
HTML5 Built-in Validation
Required Attribute
<input type="text" name="name" required>
Input Types
<input type="email" name="email">
<input type="url" name="website">
<input type="tel" name="phone">
<input type="number" name="age" min="17" max="60">
<input type="date" name="date_of_birth">
Pattern Regex
<input type="text" name="studentId" pattern="[0-9]{10}" title="StudentID must be 10 digits">
<input type="text" name="phone" pattern="08[0-9]{10}" title="Format: 08xxxxxxxxxx">
JavaScript Validation
<script>
function validateEmail(email) {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return re.test(email);
}
</script>
Password Strength
<script>
function checkPassword(password) {
let strength = 0;
if (password.length >= 8) strength++;
if (password.match(/[a-z]/) && password.match(/[A-Z]/)) strength++;
if (password.match(/[0-9]/)) strength++;
if (password.match(/[^a-zA-Z0-9]/)) strength++;
return strength;
}
</script>
Case Study: Student Registration Form
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Registration Form</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: 'Segoe UI', sans-serif; background: #f0f2f5; padding: 2rem; }
.container { max-width: 600px; margin: 0 auto; }
.card { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #1e3a5f; margin-bottom: 1.5rem; text-align: center; }
.form-group { margin-bottom: 1.5rem; }
label { display: block; margin-bottom: 0.5rem; font-weight: 500; }
input, select { width: 100%; padding: 0.8rem; border: 2px solid #ddd; border-radius: 4px; font-size: 1rem; }
input:focus, select:focus { outline: none; border-color: #3498db; }
input.valid { border-color: #2ecc71; }
input.invalid { border-color: #e74c3c; }
.error { color: #e74c3c; font-size: 0.85rem; margin-top: 0.3rem; display: none; }
.error.active { display: block; }
.hint { color: #666; font-size: 0.85rem; margin-top: 0.3rem; }
.strength-bar { height: 5px; background: #e9ecef; border-radius: 3px; margin-top: 0.5rem; }
.strength-fill { height: 100%; width: 0%; transition: all 0.3s; }
.btn { width: 100%; padding: 0.8rem; background: #3498db; color: white; border: none; border-radius: 4px; font-size: 1rem; cursor: pointer; margin-top: 1rem; }
.btn:hover { background: #2980b9; }
.btn:disabled { background: #bdc3c7; cursor: not-allowed; }
.success { background: #d4edda; color: #155724; padding: 1rem; border-radius: 4px; margin-top: 1rem; display: none; }
</style>
</head>
<body>
<div class="container">
<div class="card">
<h1>New Student Registration</h1>
<form id="registrationForm" novalidate>
<div class="form-group">
<label for="name">Full name <span style="color: red;">*</span></label>
<input type="text" id="name" name="name" placeholder="Enter your full name">
<div class="error" id="nameError">Name at least 3 characters</div>
</div>
<div class="form-group">
<label for="studentId">StudentID <span style="color: red;">*</span></label>
<input type="text" id="studentId" name="studentId" placeholder="10 digits">
<div class="error" id="studentIdError">StudentID must be 10 digits</div>
<div class="hint">Example: 1234567890</div>
</div>
<div class="form-group">
<label for="email">Email <span style="color: red;">*</span></label>
<input type="email" id="email" name="email" placeholder="[email protected]">
<div class="error" id="emailError">Invalid email</div>
</div>
<div class="form-group">
<label for="password">Password <span style="color: red;">*</span></label>
<input type="password" id="password" name="password" placeholder="At least 8 characters">
<div class="strength-bar"><div class="strength-fill" id="strengthFill"></div></div>
<div class="hint" id="passwordHint">Use a combination of uppercase, lowercase, digits, and symbols</div>
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password <span style="color: red;">*</span></label>
<input type="password" id="confirmPassword" placeholder="Confirm password">
<div class="error" id="confirmError">Passwords do not match</div>
</div>
<div class="form-group">
<label for="phone">Phone Number</label>
<input type="tel" id="phone" name="phone" placeholder="08xxxxxxxxxx">
<div class="error" id="teleponError">Format: 08 diikuti 10 digits</div>
</div>
<div class="form-group">
<label for="major">Major <span style="color: red;">*</span></label>
<select id="major" name="major">
<option value="">Select Major</option>
<option value="cs">Computer Science</option>
<option value="si">Information Systems</option>
<option value="management">Management/option>
<option value="accounting">Accounting/option>
</select>
<div class="error" id="majorError">Select your major</div>
</div>
<button type="submit" class="btn" id="submitBtn" disabled>Sign Up Now</button>
</form>
<div class="success" id="successMsg">
Registration successful! Please check your email to confirm.
</div>
</div>
</div>
<script>
const form = document.getElementById('registrationForm');
const submitBtn = document.getElementById('submitBtn');
const validators = {
name: (v) => v.length >= 3,
studentId: (v) => /^[0-9]{10}$/.test(v),
email: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v),
password: (v) => v.length >= 8,
confirmPassword: (v) => v === document.getElementById('password').value && v.length > 0,
major: (v) => v !== ''
};
function validateField(id, validator) {
const input = document.getElementById(id);
const error = document.getElementById(id + 'Error');
const isValid = validator(input.value.trim());
if (isValid) {
input.classList.remove('invalid');
input.classList.add('valid');
if (error) error.classList.remove('active');
} else if (input.value.length > 0) {
input.classList.remove('valid');
input.classList.add('invalid');
if (error) error.classList.add('active');
} else {
input.classList.remove('valid', 'invalid');
if (error) error.classList.remove('active');
}
return isValid;
}
function checkAllValid() {
const nameValid = validateField('name', validators.name);
const studentIdValid = validateField('studentId', validators.studentId);
const emailValid = validateField('email', validators.email);
const passValid = validateField('password', validators.password);
const confirmValid = validateField('confirmPassword', validators.confirmPassword);
const majorValid = validateField('major', validators.major);
submitBtn.disabled = !(nameValid && studentIdValid && emailValid && passValid && confirmValid && majorValid);
}
['name', 'studentId', 'email', 'password', 'confirmPassword', 'major'].forEach(id => {
document.getElementById(id).addEventListener('input', checkAllValid);
document.getElementById(id).addEventListener('change', checkAllValid);
});
document.getElementById('phone').addEventListener('input', function() {
validateField('phone', (v) => v === '' || /^08[0-9]{10}$/.test(v));
});
document.getElementById('password').addEventListener('input', function() {
const password = this.value;
let strength = 0;
if (password.length >= 8) strength += 25;
if (password.match(/[a-z]/) && password.match(/[A-Z]/)) strength += 25;
if (password.match(/[0-9]/)) strength += 25;
if (password.match(/[^a-zA-Z0-9]/)) strength += 25;
const fill = document.getElementById('strengthFill');
fill.style.width = strength + '%';
fill.style.background = strength <= 25 ? '#e74c3c' : strength <= 50 ? '#f39c12' : strength <= 75 ? '#3498db' : '#2ecc71';
checkAllValid();
});
form.addEventListener('submit', function(e) {
e.preventDefault();
document.getElementById('successMsg').style.display = 'block';
submitBtn.disabled = true;
});
</script>
</body>
</html>
Best Practices
- Server-side validation: Always validate on the server too
- Clear error messages: Explain what's wrong
- Real-time validation: Provide feedback while typing
- Don't rely on required alone: Add JavaScript validation
- Accessibility: Link error messages with the input
Summary
Form validation is important for data integrity and user experience. Combine HTML5 and JavaScript validation for the best results.