JavaScript validation can be split into three stages: attaching the listener, collecting field values, and applying checks. Starting with the listener, the most common approach is to intercept the form’s onsubmit event. By returning false from the handler, the default submission is prevented, giving the script a chance to examine the data first.
Once the event is caught, the next step is to grab the values from the input elements. document.getElementById is a straightforward method for this, though querySelector offers a more flexible alternative if the form structure grows. Storing the values in variables lets the script apply logic cleanly and readably.
Validation logic itself can be broken down into a few essential checks:
Required fields: Verify that the field is not empty. A simple truthy check or a length test suffices.
Email format: A regular expression can test for a general email pattern. The pattern does not need to cover every edge case but should reject clearly malformed strings.
Phone number: Depending on the locale, a pattern that accepts digits only, possibly with spaces or dashes, keeps the input tidy.
Password strength: A regex that enforces a minimum length and a mix of character classes protects against weak credentials.
Below is a compact example that shows each of these checks in action. The code is intentionally readable, with clear variable names and inline comments that explain the purpose of each section.
Prompt
// Grab form and attach listener</p>
<p>const form = document.getElementById('myForm');</p>
<p>form.addEventListener('submit', validateForm);</p>
<p>function validateForm(event) {</p>
<p>
// Stop the form from submitting</p>
<p>
event.preventDefault();</p>
<p>
// Retrieve values</p>
<p>
const name
= document.getElementById('name').value.trim();</p>
<p>
const email
= document.getElementById('email').value.trim();</p>
<p>
const phone
= document.getElementById('phone').value.trim();</p>
<p>
const password = document.getElementById('password').value;</p>
<p>
// Define patterns</p>
<p>
const emailPattern = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;</p>
<p>
const phonePattern = /^\\d{10}$/;</p>
<p>
const passwordPattern = /^(?=.<em>[a-z])(?=.</em>[A-Z])(?=.*\\d).{8,}$/;</p>
<p>
// Required check</p>
<p>
if (!name) {</p>
<p>
alert('Name is required.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// Email check</p>
<p>
if (!emailPattern.test(email)) {</p>
<p>
alert('Please enter a valid email address.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// Phone check</p>
<p>
if (!phonePattern.test(phone)) {</p>
<p>
alert('Phone number must be 10 digits.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// Password check</p>
<p>
if (!passwordPattern.test(password)) {</p>
<p>
alert('Password must be at least 8 characters and include uppercase, lowercase, and a number.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// If all checks pass, submit the form</p>
<p>
form.submit();</p>
<p>}</p>
Although this example uses the alert function for simplicity, real‑world applications typically display inline messages or use a dedicated notification area. The key takeaway is that each validation rule is a small, testable unit of code that can be reused, replaced, or extended without touching the rest of the logic.
Prompt
// Attach listener</p>
<p>const form = document.getElementById('signupForm');</p>
<p>form.addEventListener('submit', async validateForm);</p>
<p>async function validateForm(event) {</p>
<p>
const username
= document.getElementById('username').value.trim();</p>
<p>
const password
= document.getElementById('password').value;</p>
<p>
const confirmPass
= document.getElementById('confirmPassword').value;</p>
<p>
const startDateStr = document.getElementById('startDate').value;</p>
<p>
const endDateStr
= document.getElementById('endDate').value;</p>
<p>
// Username availability</p>
<p>
const usernameOk = await checkUsername(username);</p>
<p>
if (!usernameOk) {</p>
<p>
alert('Username already taken.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// Password confirmation</p>
<p>
if (password !== confirmPass) {</p>
<p>
alert('Passwords do not match.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// Date range</p>
<p>
const startDate = new Date(startDateStr);</p>
<p>
const endDate
= new Date(endDateStr);</p>
<p>
if (endDate
<p>
alert('End date must be after start date.');</p>
<p>
return;</p>
<p>
}</p>
<p>
// All checks passed</p>
<p>
form.submit();</p>
<p>}</p>
<p>async function checkUsername(name) {</p>
<p>
const res = await fetch('/api/check-username?name=' + encodeURIComponent(name));</p>
<p>
const data = await res.json();</p>
<p>
return data.available;</p>
<p>}</p>
Complex validation scripts can become large, but structuring the logic into small, focused functions - like checkUsername - keeps the code manageable. Each function can be unit‑tested independently, improving maintainability and reliability.
When the form loads, all error elements are hidden. During validation, showError is called for each field that fails a check. Once the user corrects an input, calling clearError removes the visual hint and clears the text. This approach keeps the user’s focus on the action needed rather than on an abstract error state.
Accessibility is an extra layer to consider. The aria-invalid attribute should be set to true on inputs that fail validation. This signals assistive technology that the input is in an error state. Additionally, aria-describedby can reference the error message’s ID, allowing screen readers to announce the specific issue.
Combining inline text, visual styling, and ARIA attributes creates a comprehensive feedback system that works for all users. The user learns exactly what to correct and how, without being overwhelmed by vague prompts.
Javascript Form Validation Example
The following example ties together the concepts discussed earlier. It features a form with name, email, phone, and password fields, each subject to validation rules. Error messages appear inline, and the success message is displayed once all checks pass.
Open the code in a browser to see how the validation logic operates step by step. Notice how the script prevents submission until every field satisfies its rule.
Each input has a dedicated error element that appears only when the field fails validation.
CSS classes toggle visual styling, and ARIA attributes keep the experience accessible.
Validation logic is encapsulated in reusable showError and clearError functions, keeping the main event handler concise.
The form’s novalidate attribute tells the browser to skip its built‑in validation, letting the script handle all checks.
Adapting this pattern to other forms - whether a newsletter signup or a multi‑step checkout - follows the same principles. By reusing the same validation functions and patterns, developers maintain consistency across the site.
That concludes a full, hands‑on example of JavaScript form validation that balances clarity, accessibility, and efficiency. Implementing these strategies will lead to cleaner data, happier users, and a smoother development workflow.
No comments yet. Be the first to comment!