JavaScript Forms and Validation: Read, Check and Show Errors
Learn how JavaScript reads form controls, validates user input and shows clear custom error messages before submission.
What you will learn
Forms are one of the main ways websites collect information. Login pages, registration pages, checkout pages, search boxes and contact forms all depend on form controls.
In this lesson you will learn how JavaScript reads form values, checks checkboxes, validates input and displays useful custom error messages.
The concept
A form can contain many controls:
<form>
<input type="text">
<input type="email">
<input type="number">
<input type="checkbox">
<select>
<option>India</option>
<option>Japan</option>
</select>
<textarea></textarea>
<button type="submit">Submit</button>
</form>
JavaScript can read these controls and decide whether the data is acceptable.
The most important properties in this lesson are:
| Control | Common property |
|---|---|
| Text, email, number inputs | .value |
| Checkbox | .checked |
| Select | .value |
| Textarea | .value |
Reading .value
For most text-like form controls, use .value.
<input id="username" type="text">
const username = document.getElementById("username").value;
console.log(username);
If the user types:
Riya
then:
console.log(username);
prints:
Riya
.value gives a string
Even a number input normally gives you a string:
<input id="age" type="number">
const age = document.getElementById("age").value;
console.log(age);
console.log(typeof age); // "string"
Convert it when you need a number:
const age = Number(document.getElementById("age").value);
console.log(typeof age); // "number"
Tip: Form input is user input. Treat it as untrusted data and validate it before using it.
Reading .checked
Checkboxes work differently. Use .checked.
<label>
<input id="terms" type="checkbox">
I agree to the terms
</label>
const accepted = document.getElementById("terms").checked;
console.log(accepted);
The result is always a boolean:
true
or:
false
Do not use .value when your question is “Is this checkbox selected?”
Handling form submission
The most common pattern is listening to the form’s submit event.
<form id="login-form">
<input id="email" type="email">
<button type="submit">Login</button>
</form>
const form = document.getElementById("login-form");
form.addEventListener("submit", function (event) {
event.preventDefault();
const email = document.getElementById("email").value;
console.log(email);
});
event.preventDefault() stops the browser’s normal form submission so your JavaScript can validate and process the data first.
Why validation matters
Imagine a registration form asking for:
- Name
- Age
- Password
- Terms agreement
You do not want to accept:
Name: empty
Email: hello
Age: -5
Terms: not checked
Validation checks whether the submitted data meets your rules.
Common rules include:
- Required field
- Minimum or maximum length
- Valid email format
- Number in a specific range
- Password requirements
- Checkbox must be checked
Required field validation
A simple required check:
const name = document.getElementById("name").value.trim();
if (name === "") {
console.log("Name is required.");
}
Why use trim()?
const name = " ";
console.log(name.trim() === ""); // true
This prevents a user from entering only spaces to bypass a basic required-field check.
Number validation
Remember that .value is a string.
const age = Number(document.getElementById("age").value);
if (!Number.isInteger(age) || age < 18) {
console.log("Age must be a whole number of 18 or more.");
}
If the input is empty, Number("") becomes 0, so it is often useful to check the original value first when an empty field has a different meaning.
const rawAge = document.getElementById("age").value.trim();
if (rawAge === "") {
console.log("Age is required.");
} else {
const age = Number(rawAge);
if (!Number.isInteger(age) || age < 18) {
console.log("Enter a valid age.");
}
}
Email validation
For simple client-side validation, you can use the browser’s email input:
<input id="email" type="email">
You can also check whether the field is empty:
const email = document.getElementById("email").value.trim();
if (email === "") {
console.log("Email is required.");
}
For many applications, the browser’s built-in validation is enough for basic format checking. If your application has specific rules, you can add custom checks.
For example:
if (!email.includes("@")) {
console.log("Please enter an email address.");
}
This is only a simple teaching example, not a complete email parser.
Custom validation
Custom validation means you decide the rules.
Suppose a username must:
- contain at least 3 characters
- not contain spaces
const username = document.getElementById("username").value.trim();
if (username === "") {
console.log("Username is required.");
} else if (username.length < 3) {
console.log("Username must have at least 3 characters.");
} else if (username.includes(" ")) {
console.log("Username cannot contain spaces.");
}
Another example:
const password = document.getElementById("password").value;
if (password.length < 8) {
console.log("Password must contain at least 8 characters.");
}
The exact rules depend on your application.
Showing error messages
A good form should tell the user what is wrong and how to fix it.
HTML:
<input id="email" type="email">
<p id="email-error"></p>
JavaScript:
const email = document.getElementById("email").value.trim();
const emailError = document.getElementById("email-error");
if (email === "") {
emailError.textContent = "Email is required.";
} else {
emailError.textContent = "";
}
This is much more useful than:
alert("Error");
The user can immediately see which field needs attention.
A complete validation example
<form id="signup-form" novalidate>
<label>
Name
<input id="name" type="text">
</label>
<label>
Email
<input id="email" type="email">
</label>
<label>
Age
<input id="age" type="number">
</label>
<label>
<input id="terms" type="checkbox">
I agree to the terms
</label>
<button type="submit">Create Account</button>
<p id="message"></p>
</form>
const form = document.getElementById("signup-form");
const message = document.getElementById("message");
form.addEventListener("submit", function (event) {
event.preventDefault();
const name = document.getElementById("name").value.trim();
const email = document.getElementById("email").value.trim();
const ageText = document.getElementById("age").value.trim();
const terms = document.getElementById("terms").checked;
if (name === "") {
message.textContent = "Please enter your name.";
return;
}
if (email === "") {
message.textContent = "Please enter your email.";
return;
}
const age = Number(ageText);
if (ageText === "" || !Number.isInteger(age) || age < 18) {
message.textContent = "Please enter a valid age of 18 or above.";
return;
}
if (!terms) {
message.textContent = "Please accept the terms.";
return;
}
message.textContent = "Registration successful!";
});
Notice the flow:
- Stop the default submission.
- Read the values.
- Validate each rule.
- Show a useful message when something is wrong.
- Stop further processing with
return. - Continue only when all checks pass.
Multiple field errors
For larger forms, one message at the bottom is not always enough.
A better structure is:
<label>
Email
<input id="email" type="email">
<small id="email-error"></small>
</label>
Then:
const emailError = document.getElementById("email-error");
if (email === "") {
emailError.textContent = "Email is required.";
} else {
emailError.textContent = "";
}
You can do the same for every field.
A useful improvement is to add an error class:
input.classList.add("error");
and remove it when the field becomes valid:
input.classList.remove("error");
Browser validation vs custom validation
HTML already provides useful validation:
<input type="email" required>
You can also use:
<input type="text" minlength="3" maxlength="20" required>
and:
<input type="number" min="18" max="100">
JavaScript is useful when the rule depends on your application’s logic.
For example:
if (password !== confirmPassword) {
// custom validation
}
Tip: Client-side validation improves user experience, but it is not a security boundary. A server must validate important data again.
Common mistakes
- Forgetting that
.valueis usually a string. Convert it withNumber()when numeric calculations are required. - Using
.valuefor a checkbox. Use.checkedto know whether it is selected. - Validating only when the user clicks a separate button. Listening to the form’s
submitevent keeps the validation tied to submission. - Forgetting
event.preventDefault(). The browser may submit/reload the page before your custom processing finishes. - Showing vague messages such as “Invalid input.” Tell the user what to fix.
- Accepting whitespace as a name or username. Use
.trim(). - Trusting client-side validation for security. Always validate important data on the server too.
- Using
alert()for every error. Inline messages are usually easier for users to understand and fix.
Practice
- Create a form with name, email and age fields. Validate all three.
- Add a checkbox for “I agree” and prevent submission when it is unchecked.
- Show a separate error message below each invalid field.
- Add a password field that requires at least 8 characters.
- Add a confirm-password field and check that both passwords match.
- Challenge: Create a registration form with name, email, age, password, confirm password and terms checkbox.
- Challenge: Add CSS classes so invalid fields get a visible error style and valid fields get a success style.
Recap
- Use
.valueto read most text-like form controls. - Use
.checkedfor checkboxes. - Form values commonly arrive as strings, even from number inputs.
- Use the
submitevent to handle form submission. - Use
event.preventDefault()when you want to process the form with JavaScript first. - Validation checks whether user input follows your rules.
- Good error messages tell users what went wrong and how to fix it.
- Client-side validation improves UX but server-side validation is still required for important data.