JavaScript: Forms & Validation
Learn how to access form elements, handle submissions, validate user input, and build a great form experience with JavaScript.
Accessing Form Elements
You can access a form and its inputs using standard DOM selectors or the form's elements collection, which lets you target fields by their name attribute.
Selecting Form Elements
Forms and their fields can be accessed by ID, name, or through the form's built-in elements collection.
- document.getElementById('id'): target a specific input by ID
- document.querySelector('form'): select the form element itself
- form.elements['name']: access a field by its name attribute
- form.elements: an HTMLFormControlsCollection of all fields
Accessing Form Fields
Read input references using the form's elements collection.
const form = document.getElementById("myForm");
// Access by name via elements collection
const username = form.elements["username"];
const email = form.elements["email"];
console.log("Username field tag:", username.tagName);
console.log("Email field name:", email.name);Getting and Setting Input Values
The value property reads the current text in an input and can also be assigned to pre-fill or clear the field.
input.value
The value property is the primary way to read and write what a user has typed into a text input, textarea, or select.
- input.value: returns the current field value as a string
- Assign to it to set the value: input.value = 'Hello'
- input.value = '': clears the field
- For checkboxes, use input.checked (boolean) instead of value
- For select elements, select.value returns the selected option's value
Reading and Writing input.value
Get the typed value or assign a new one programmatically.
const field = document.getElementById("field");
const output = document.getElementById("output");
document.getElementById("readBtn").addEventListener("click", () => {
output.textContent = "Value: " + field.value;
});
document.getElementById("setBtn").addEventListener("click", () => {
field.value = "Pre-filled text";
output.textContent = "Value set!";
});Form Submission Handling
By default, submitting a form reloads the page. Intercept the submit event and call e.preventDefault() to handle the data with JavaScript instead.
Handling submit
Preventing the default submit action lets you validate data, show errors, or send it via fetch without a page reload.
- Listen on the form element, not the button: form.addEventListener('submit', fn)
- Always call e.preventDefault() first to stop the page reload
- Read field values inside the handler after the user submits
- Show success or error feedback in the UI instead of relying on page state
Intercept Form Submit
Handle the form with JS instead of a page reload.
const form = document.getElementById("loginForm");
const feedback = document.getElementById("feedback");
form.addEventListener("submit", function (e) {
e.preventDefault(); // stop page reload
const user = document.getElementById("user").value;
const pass = document.getElementById("pass").value;
feedback.textContent = `Submitted: ${user} / ${pass.length} chars`;
});Form Events
Beyond submit, forms emit several useful events that let you respond to user interaction in real time.
Form Event Types
Each form event fires at a different moment in the user interaction lifecycle.
- submit: form submitted (button click or Enter key)
- input: fires on every character typed (live updates)
- change: fires when focus leaves and the value has changed
- focus: field receives keyboard/click focus
- blur: field loses focus (good for validation triggers)
Form Event Demo
Watch input, change, focus, and blur fire as you interact.
const box = document.getElementById("box");
const log = document.getElementById("log");
box.addEventListener("focus", () => log.textContent = "Event: focus");
box.addEventListener("input", () => log.textContent = "Event: input | " + box.value);
box.addEventListener("change", () => log.textContent = "Event: change | " + box.value);
box.addEventListener("blur", () => log.textContent = "Event: blur");Client-side Validation
Client-side validation checks user input in the browser before it is sent to the server. It gives instant feedback and reduces unnecessary network requests, but it must always be paired with server-side validation.
Validation Strategy
Client-side validation improves UX. It should never replace server-side validation because browser checks can be bypassed.
- Validate on blur to check a field when the user moves away
- Validate on submit to check everything before sending
- Show inline error messages near the relevant field
- Never trust client validation alone on the server
Basic Required Field Check
Show an error message if the name field is empty on submit.
const form = document.getElementById("form");
const nameInput = document.getElementById("name");
const nameError = document.getElementById("nameError");
form.addEventListener("submit", (e) => {
e.preventDefault();
if (nameInput.value.trim() === "") {
nameError.textContent = "Name is required.";
} else {
nameError.textContent = "";
console.log("Form is valid:", nameInput.value);
}
});Email Validation with Regex
A regular expression can verify that the user has typed something that looks like a valid email address before the form is submitted.
Email Regex
The pattern /^\\S+@\\S+\\.\\S+$/ is a simple but effective check for the shape of an email address.
- /^\S+@\S+\.\S+$/: requires non-whitespace chars, an @, a dot, and a domain
- Use regex.test(value) to return true/false
- For stricter validation, use an
input type='email'and rely on built-in browser checking - Always validate email on the server too, regex only checks format, not existence
Email Regex Validation
Test whether the entered value matches an email pattern.
const emailInput = document.getElementById("email");
const result = document.getElementById("result");
document.getElementById("check").addEventListener("click", () => {
const value = emailInput.value.trim();
const emailRegex = /^S+@S+.S+$/;
if (emailRegex.test(value)) {
result.textContent = "Valid email!";
result.style.color = "green";
} else {
result.textContent = "Invalid email format.";
result.style.color = "red";
}
});Number and Length Validation
Use isNaN() or Number() to check numeric input, and value.length to enforce minimum or maximum character counts.
Number and Length Checks
These two checks cover the most common field constraints beyond required-field validation.
- isNaN(value): true if the value cannot be parsed as a number
- Number(value): converts a string to a number; NaN if not valid
- value.length: number of characters typed
- Use value.length >= min && value.length <= max for length range checks
Number and Length Validators
Reusable validation functions for numeric range and string length.
Press Run to execute the code and see output here.
FormData API
The FormData object automatically collects all form field values using their name attributes. It works seamlessly with fetch for submitting data to a server.
FormData
FormData reads the entire form at once, no need to query each field individually. It also handles file inputs and multipart encoding automatically.
- new FormData(formElement): collect all named fields at once
- formData.get('name'): read a single field value
- formData.set('key', value): add or update a field
- Pass FormData directly as the body in a fetch POST request
- Use Object.fromEntries(formData) to convert to a plain object
FormData Collection
Collect all field values at once using FormData.
const form = document.getElementById("signupForm");
const output = document.getElementById("output");
form.addEventListener("submit", (e) => {
e.preventDefault();
const data = new FormData(form);
const plain = Object.fromEntries(data); // convert to object
output.textContent = JSON.stringify(plain, null, 2);
});Custom Validation Messages
The Constraint Validation API lets you set custom messages that appear in the browser's native tooltip when a field fails validation. Call setCustomValidity() with a message to mark a field invalid, or an empty string to clear it.
setCustomValidity()
Native browser validation tooltips can be customised per-field with setCustomValidity, giving you control over the message without a custom UI.
- input.setCustomValidity('message'): mark invalid with a custom tooltip
- input.setCustomValidity(''): clear the custom error (mark valid)
- input.checkValidity(): returns true if the field passes all constraints
- input.reportValidity(): shows the browser tooltip immediately
Custom Validity Message
Set a custom browser validation message on a specific field.
const form = document.getElementById("form");
const code = document.getElementById("code");
const msg = document.getElementById("msg");
const VALID_CODE = "DEVORA2024";
code.addEventListener("input", () => {
if (code.value !== VALID_CODE && code.value.length > 0) {
code.setCustomValidity("Invalid invite code.");
} else {
code.setCustomValidity(""); // clear error
}
});
form.addEventListener("submit", (e) => {
e.preventDefault();
if (code.checkValidity()) {
msg.textContent = "Access granted!";
} else {
code.reportValidity(); // show browser tooltip
}
});Putting It All Together
A real form combines required checks, format validation, and live feedback. This example validates a username (length) and email (regex) on submit and shows inline error messages.
Complete Validation Pattern
Combine multiple validation rules in a single submit handler to give users clear, field-level error messages.
- Validate every field in sequence and collect all errors before showing them
- Show errors adjacent to the failing field, not in an alert
- Re-validate on input so errors disappear as soon as the user fixes them
- Only submit data when all fields pass
Full Registration Validation
Validate username length and email format on submit.
const form = document.getElementById("regForm");
const uname = document.getElementById("uname");
const mail = document.getElementById("mail");
const emailRegex = /^S+@S+.S+$/;
function validate() {
let valid = true;
if (uname.value.trim().length < 3 || uname.value.trim().length > 20) {
document.getElementById("unameErr").textContent = "Must be 3-20 characters.";
valid = false;
} else {
document.getElementById("unameErr").textContent = "";
}
if (!emailRegex.test(mail.value.trim())) {
document.getElementById("mailErr").textContent = "Enter a valid email.";
valid = false;
} else {
document.getElementById("mailErr").textContent = "";
}
return valid;
}
form.addEventListener("submit", (e) => {
e.preventDefault();
if (validate()) {
document.getElementById("success").textContent = "Registered successfully!";
}
});Knowledge Check
1. Which property returns the current value of a text input?
2. Which event fires on every keystroke inside an input field?
3. What does e.preventDefault() do when used on a form submit event?
4. Which regex pattern correctly validates a basic email address?
5. Which API collects all form field values using their name attributes?
6. Which property sets a custom browser validation tooltip on an input?
7. Which event fires only when an input loses focus AND its value has changed?
8. How do you access a form element by its name attribute?