In this article · 5 sections
A booking form that rejects input with an unclear message loses customers. JavaScript form validation done well catches mistakes early, explains how to fix them and keeps the form easy to use, especially on phones.
Start with HTML5 attributes
<form id="booking" novalidate>
<label for="name">Your name</label>
<input id="name" name="name" required minlength="2" autocomplete="name">
<small class="error" id="name-error"></small>
<label for="phone">Mobile number</label>
<input id="phone" name="phone" type="tel" inputmode="numeric" required
pattern="[6-9][0-9]{9}" maxlength="10" autocomplete="tel">
<small class="error" id="phone-error"></small>
<label for="date">Travel date</label>
<input id="date" name="date" type="date" required>
<small class="error" id="date-error"></small>
<button type="submit">Get Fare</button>
</form>
inputmode="numeric"opens the number keypad on phones- The pattern accepts 10-digit Indian mobile numbers starting 6–9
novalidatelets us show our own friendly messages instead of browser popups
JavaScript using the Constraint Validation API
const form = document.querySelector('#booking');
const date = form.querySelector('#date');
date.min = new Date().toISOString().split('T')[0]; // no past dates
const messages = {
name: { valueMissing: 'Please enter your name.', tooShort: 'Name looks too short.' },
phone: { valueMissing: 'Please enter your mobile number.', patternMismatch: 'Enter a 10-digit mobile number, e.g. 9876543210.' },
date: { valueMissing: 'Please choose your travel date.', rangeUnderflow: 'Travel date cannot be in the past.' }
};
function showError(input) {
const box = form.querySelector('#' + input.id + '-error');
let msg = '';
for (const key in messages[input.name]) {
if (input.validity[key]) { msg = messages[input.name][key]; break; }
}
box.textContent = msg;
input.setAttribute('aria-invalid', msg ? 'true' : 'false');
input.setAttribute('aria-describedby', box.id);
return !msg;
}
form.querySelectorAll('input').forEach(input => {
input.addEventListener('blur', () => showError(input));
input.addEventListener('input', () => { if (input.getAttribute('aria-invalid') === 'true') showError(input); });
});
form.addEventListener('submit', (e) => {
let firstBad = null;
form.querySelectorAll('input').forEach(input => {
if (!showError(input) && !firstBad) firstBad = input;
});
if (firstBad) { e.preventDefault(); firstBad.focus(); }
});
UX rules
- Validate on blur (when leaving a field), not on every keystroke at first
- Put errors next to the field, in plain language, with an example
- Don't clear what the user typed
- Mark errors with text, not only red colour. See accessibility basics
- Ask only for what you need; every extra field lowers conversions
Always validate on the server too
JavaScript can be disabled or bypassed. Repeat the checks in PHP before saving or emailing. See PHP for beginners and PHP contact form with PHPMailer.
FAQs
Should I strip +91 and spaces?
Yes. Clean input in JavaScript and PHP (keep digits, take the last 10) rather than rejecting it.
Can I submit without reloading?
Yes, with fetch. See fetch and AJAX tutorial.
Was this article helpful?
Your answer helps us improve our guides