Forms
| Read inputs | |
| Validate on submit | |
| Show errors | |
| preventDefault |
Read inputs
Form fields arrive as generic elements, so ask for the concrete kind. querySelector with HTMLInputElement unlocks value, and a null check guarantees the field exists before reading:
const nameInput = document.querySelector<HTMLInputElement>("#name");
if (nameInput === null) {
throw new Error("missing #name");
}
const name: string = nameInput.value.trim();
value is always a string, even for numbers, so convert with Number when math is needed. trim drops accidental spaces before validation ever sees the text.
Validate on submit
Check the values in one function that returns either an error message or nothing. Pure checks like length tests stay easy to unit test without any page at all:
function checkName(name: string): string | null {
if (name.length === 0) {
return "Name is required";
}
if (name.length < 2) {
return "Name is too short";
}
return null;
}
null means valid, a string means broken. That tiny protocol keeps the submit handler below to one branch.
Show errors
Errors belong next to the field they describe. Write the message into a small hint element and highlight the input with a class. Clear both when the value turns valid, so old complaints never linger:
function showError(input: HTMLInputElement, message: string | null): void {
const hint = document.querySelector("#name-error");
if (hint !== null) {
hint.textContent = message ?? "";
}
input.classList.toggle("invalid", message !== null);
}
The double question marks fall back to an empty string, which clears the hint. toggle with a second argument adds the class exactly when a message exists.
preventDefault
The submit event fires before the browser sends the form. Building on the helpers above, listen on the form, stop the default send with preventDefault when validation fails, and let valid data through untouched:
const form = document.querySelector<HTMLFormElement>("form");
if (form === null) {
throw new Error("missing form");
}
form.addEventListener("submit", (event) => {
const problem = checkName(nameInput.value.trim());
showError(nameInput, problem);
if (problem !== null) {
event.preventDefault();
}
});
preventDefault cancels the page reload, so the user reads the hint and fixes the field in place. Valid submits skip the branch and travel to the server as usual.
Next: Web storage
Article author: Arthur Isaev