Module 8 - Strings, Validation and Regular Expressions

Introduction to Strings

In JavaScript, strings are one of the most commonly used data types. Strings are sequences of characters, numbers, or symbols, used to represent text and are fundamental in web development. They help in tasks like displaying messages, gathering and processing user input, creating URLs, and much more. In this lesson, we will explore the properties of strings, how to create and manipulate them, and how to use templates to make our code more dynamic and readable.

Basic Forms of Strings

JavaScript supports three ways to declare strings:

Single Quotes (' '):

let greeting = 'Hello, World!';


Double Quotes (" "):

let greeting = "Hello, World!";


Template Literals (Backticks ````):

let greeting = `Hello, World!`;


Each format has its use cases, though single and double quotes work similarly. However, template literals provide additional flexibility, particularly with embedding expressions and handling multi-line text.



Template Literals and Embedded Expressions

Template literals, enclosed in backticks, allow us to create strings that can include expressions and variables directly inside the string. This makes them especially useful for dynamic content.

let userName = "Sam";
let message = `Hello, ${userName}! Welcome back.`;
console.log(message); // Output: Hello, Sam! Welcome back.


Using ${expression} inside backticks allows us to insert variables, perform calculations, or even call functions within a string.



Common String Properties and Methods

JavaScript provides various properties and methods to work with strings. Below are some key ones:

.length: Returns the length (number of characters) in a string.

let phrase = "JavaScript";
console.log(phrase.length); // Output: 10


.toUpperCase() and .toLowerCase(): Converts a string to upper or lower case.

let text = "Hello";
console.log(text.toUpperCase()); // Output: HELLO


.charAt(index): Returns the character at a specified index.

let word = "JavaScript";
console.log(word.charAt(4)); // Output: S


.indexOf(substring): Finds the index of the first occurrence of a substring. Returns -1 if not found.

let sentence = "JavaScript is fun!";
console.log(sentence.indexOf("fun")); // Output: 15


.slice(start, end): Extracts a part of a string based on the specified start and end positions.

let text = "Hello, world!";
console.log(text.slice(0, 5)); // Output: Hello


.replace(oldSubstring, newSubstring): Replaces a specified part of a string with another string.

let greeting = "Hello, John!";
console.log(greeting.replace("John", "Alice")); // Output: Hello, Alice!


These methods make it easy to retrieve, modify, and inspect string data.



String Manipulation Techniques

Concatenation

Combining multiple strings together. With template literals, we don’t need to use the + operator, but it’s still useful to understand.

let firstName = "Jane";
let lastName = "Doe";
let fullName = firstName + " " + lastName;

Splitting and Joining Strings

Using .split() allows a string to be divided into an array of substrings, and .join() can combine array elements into a single string.

let sentence = "This is a test sentence.";
let words = sentence.split(" ");
console.log(words); // Output: ['This', 'is', 'a', 'test', 'sentence.']

let joined = words.join("-");
console.log(joined); // Output: This-is-a-test-sentence.

Trimming Whitespace

.trim() removes whitespace from both ends of a string, which is especially useful in form validation when users might accidentally add spaces.

let input = "   Hello!   ";
console.log(input.trim()); // Output: Hello!


String Interpolation for Readability

When you need to embed variables or expressions, string interpolation (through template literals) improves readability.

let price = 25;
let product = "coffee mug";
let message = `The price of the ${product} is $${price}.`;
console.log(message);


Escaping Characters in Strings

When using quotes inside a string, certain characters need to be “escaped” with a backslash (\). For instance:

let quote = "He said, \"JavaScript is amazing!\"";

JavaScript also supports special escape sequences:

  • \n for a new line
  • \t for a tab
  • \\ for a backslash


Introduction to Form Validation

Form validation is a crucial aspect of web development. It ensures that users enter the correct information before submitting a form, which helps improve data quality and enhances user experience. JavaScript allows us to perform form validation on the client side, meaning checks occur in the browser before data is sent to a server. Let’s break down some essential aspects of form validation.

Purpose of Form Validation

Form validation has several key purposes:

  • Data Integrity: By checking user input before submission, we reduce errors, inconsistencies, and invalid data in the database.
  • User Guidance: Validation helps users know if they’ve missed required information or entered data in an incorrect format, providing an overall better experience.
  • Enhanced Security: Some validation checks can prevent malicious input, reducing the risk of attacks like SQL injection.
  • Resource Optimization: Validating data on the client side reduces the burden on the server, as the browser handles many common validation tasks, potentially reducing server processing and database errors.

For example, if a form requires an email address, we can use validation to ensure the user enters a valid email format like example@domain.com. Without this, users might submit invalid data, leading to incorrect or unusable information.

Client-Side vs. Server-Side Validation

When it comes to form validation, there are two primary types: client-side and server-side validation.

Client-Side Validation:

  • Performed in the user’s browser before the data is sent to the server.
  • Allows immediate feedback (e.g., showing error messages instantly if required fields are empty).
  • Reduces server load since invalid data can be prevented from reaching the server.
  • Not foolproof, as users can bypass or disable JavaScript, so it should be seen as a convenience, not as the sole defense.

Server-Side Validation:

  • Takes place on the server after data is submitted.
  • Necessary to ensure data integrity and security, as client-side validation can be bypassed.
  • Protects against malicious input by re-checking data on the server, where validation cannot be disabled or manipulated by users.

Client-side validation improves user experience by providing instant feedback, while server-side validation is essential for security and reliability.

Advantages of Using JavaScript for Form Validation

JavaScript is the primary language for implementing client-side validation for several reasons:

  1. Immediate Feedback: JavaScript can check the user’s input as they type or when they submit the form. This provides real-time feedback, which improves user experience.
  2. Better User Experience: By providing inline feedback, JavaScript makes forms more user-friendly and less frustrating, helping users understand exactly what needs to be corrected.
  3. Performance Efficiency: JavaScript validation reduces the number of requests sent to the server since it catches common errors before form submission, thus lowering the server load.
  4. Customizable Validation Logic: JavaScript allows you to create custom validation logic that can be as simple or complex as required. This flexibility is essential for forms that need specific, non-standard validations.

JavaScript is a versatile and effective tool for form validation, particularly for common, straightforward checks that improve usability and performance.

Types of Validation

Understanding the types of validations commonly used in web forms will help us determine which checks to implement in our JavaScript code. Here are a few key validation types:

  • Required Fields: Ensures that certain fields are not left empty. For example, a form asking for user registration typically requires fields like username, email, and password to be completed.
  • Data Type Validation: Verifies that the input data matches a specific type, such as numbers, strings, or dates. For example, age fields should contain numbers, not text.
  • Range Checks: Ensures values fall within a specific range. For instance, an age field might only accept values between 18 and 99. JavaScript can easily check if a number is within this range.
  • Format Validation: Confirms that data follows a specified format, like an email address format (e.g., user@example.com). Patterns can help match phone numbers, ZIP codes, and other standardized data types.
  • Custom Validation Rules: Allows for rules specific to the needs of a particular form. For example, a password field might require a minimum length and certain characters to ensure strong passwords.

Each type of validation improves the reliability of the data collected, and JavaScript can implement these validations in various ways.

Key Form Validation Examples

Let’s look at a few specific examples of how form validation can be applied to real-world scenarios:

Checking for Required Fields:

  • Many forms have fields that must be completed (such as email and password). JavaScript can verify that these fields are filled before allowing the form to submit.
  • For example, a simple JavaScript check could be written to ensure that a text input for “username” is not left blank.

Data Type Validation:

  • If you have a field for entering age, you want to ensure users enter a number, not text. JavaScript can check for numbers using built-in functions or type-checking operators.

Pattern Validation (Format Validation):

  • For email addresses, we need to confirm the entry matches a format like example@domain.com. Although regular expressions are often used for this, simpler checks may involve JavaScript methods to look for the “@” and “.” symbols.

Range Checks:

  • A product quantity field could require a number between 1 and 100. JavaScript allows us to set this limit and validate the input accordingly, displaying an error if the value is outside this range.

Custom Rules for Enhanced User Experience:

  • A password input may require at least one uppercase letter, one number, and be at least 8 characters long. Though regular expressions can help here, simpler JavaScript functions can check for character presence and length without regex.


Basic Validation Techniques

In this section, we’ll explore how to perform essential form validation tasks using JavaScript without delving into regular expressions. These techniques will help ensure users enter the correct data formats and complete required fields, providing immediate feedback to improve the form experience.

Checking for Empty Fields

One of the most common validation tasks is checking that required fields are not left empty. This prevents users from submitting forms without filling in essential information.

Basic Check for Empty Input

You can use value properties of input fields to determine if a user has entered any data:

function validateForm() {
let username = document.getElementById("username").value;
if (username === "") {
alert("Username must be filled out.");
return false; // Stops form submission
}
}

Using .trim() for Extra Whitespace

Sometimes users may enter only spaces, which could be considered empty. Using .trim() removes whitespace from both ends of a string, ensuring the user has entered actual content:

if (username.trim() === "") {
alert("Username cannot be empty or just spaces.");
return false;
}

This basic check helps ensure that the form has all necessary data before submission.

Validating Numeric and Text Fields

Some form fields require specific types of data, like numbers for age or text for a name. Here are techniques for each:

Numeric Fields

Use isNaN() to check if a value is not a number (NaN stands for “Not a Number”).

let age = document.getElementById("age").value;
if (isNaN(age) || age === "") {
alert("Please enter a valid number for age.");
return false;
}

Ensuring Positive Numbers Only

For age or other fields requiring positive numbers, you can also check if the number is greater than 0.

if (isNaN(age) || age <= 0) {
alert("Please enter a valid age greater than 0.");
return false;
}

Text Fields

For fields like names that should contain only letters, you can check for non-empty values and restrict numbers (later, we can refine this with regular expressions).

let name = document.getElementById("name").value;
if (name.trim() === "" || !isNaN(name)) {
alert("Please enter a valid name (letters only).");
return false;
}

These simple checks handle many common field requirements.

Techniques for Dropdowns, Checkboxes, and Radio Buttons

Other form elements, like dropdowns, checkboxes, and radio buttons, require different validation techniques:

Dropdown Menus:

  • Often, dropdowns have a default option like “Select an option” with an empty or placeholder value.
  • Check that the user has chosen a different option.
let country = document.getElementById("country").value;
if (country === "") {
alert("Please select a country.");
return false;
}

Checkboxes

Checkboxes are commonly used for terms and conditions. You can validate if at least one is checked or if a specific checkbox (like “Accept Terms”) is selected.

let termsAccepted = document.getElementById("terms").checked;
if (!termsAccepted) {
alert("You must accept the terms and conditions.");
return false;
}

Radio Buttons:

For radio button groups, make sure that one option is selected. This requires checking the checked property of each radio button in the group.

let gender = document.forms["myForm"]["gender"];
let selected = false;
for (let i = 0; i < gender.length; i++) {
if (gender[i].checked) {
selected = true;
break;
}
}
if (!selected) {
alert("Please select your gender.");
return false;
}

These validations help ensure that users select required options, especially in forms with multiple-choice questions or agreements.

Providing User Feedback (Error Messages and Styling)

Good form validation not only checks the data but also guides the user on how to correct errors.

  • Using alert() for Basic Feedback: alert() is a quick way to notify users of errors, but it can be disruptive since it interrupts form entry.

Displaying Inline Error Messages

Adding error messages near the fields themselves is more user-friendly. You can set the text content of an error message element and style it for visibility.

HTML:

<input type="text" id="username">
<span id="usernameError" style="color: red;"></span>

JavaScript:

function validateUsername() {
let username = document.getElementById("username").value;
let error = document.getElementById("usernameError");
if (username.trim() === "") {
error.textContent = "Username is required.";
return false;
} else {
error.textContent = ""; // Clear error
}
}

Highlighting Invalid Fields

You can also style fields with invalid data to make it clearer where errors occur. CSS classes can be toggled in JavaScript for this purpose.

CSS:

.error {
border-color: red;
}

JavaScript:

let usernameInput = document.getElementById("username");
if (username.trim() === "") {
usernameInput.classList.add("error");
} else {
usernameInput.classList.remove("error");
}

This styling helps users quickly identify fields needing correction.



Introducing Regular Expressions

Regular expressions, often called regex or regexp, are a powerful tool in programming that allow us to search, match, and manipulate text based on specific patterns. In the context of form validation, regular expressions help us check if user input follows a required format, such as an email address or a phone number. Although regex may seem complex at first, mastering basic patterns can make form validation much more effective.

What Are Regular Expressions?

A regular expression is essentially a sequence of characters that forms a search pattern. This pattern can be used to match text, identify character sequences, and extract or replace parts of a string. Regular expressions are especially useful for:

  • Pattern Matching: Ensuring user input matches specific formats, like email addresses, phone numbers, or postal codes.
  • Finding Text: Searching for certain characters or words within a string.
  • Replacing Text: Replacing parts of a string based on a matching pattern.

In JavaScript, regular expressions are represented between two forward slashes (e.g., /pattern/). Here’s a basic example:

let pattern = /abc/;
let testString = "I have abc in my text.";
console.log(pattern.test(testString)); // true, because "abc" is in the string

In this example, /abc/ is the regular expression pattern, and .test() checks if the pattern is found in the testString.

Basic Syntax and Pattern-Matching Concepts

To get started with regex, let’s explore some fundamental elements that are commonly used for form validation:

Literal Characters

Literal characters are the simplest regex components. They match the exact characters they represent. For example, /abc/ matches the exact sequence “abc” anywhere in a string.

Anchors

Anchors specify where in the text to match the pattern.

  • ^ matches the start of a string. For example, /^abc/ only matches if the string starts with “abc”.
  • $ matches the end of a string. For example, /abc$/ only matches if the string ends with “abc”.

Using both anchors together, /^abc$/ matches a string that is exactly “abc” from start to finish.

Character Classes

Character classes let you match any one of several characters within a set.

  • [abc] matches any one of the characters “a”, “b”, or “c”.
  • [0-9] matches any digit from 0 to 9.
  • [a-zA-Z] matches any uppercase or lowercase letter.

Quantifiers

Quantifiers specify how many times a character or group can appear.

* matches 0 or more occurrences of the preceding character. For example, /a*/ matches “a”, “aa”, or an empty string.

  • + matches 1 or more occurrences. For example, /a+/ matches “a”, “aa”, but not an empty string.
  • {n} specifies an exact number of occurrences. For instance, /a{3}/ only matches “aaa”.
  • {n,m} specifies a range of occurrences, matching from n to m times. For example, /a{2,4}/ matches “aa”, “aaa”, or “aaaa”.

Special Characters

Special characters match specific types of characters.

  • \d matches any digit (equivalent to [0-9]).
  • \D matches any non-digit.
  • \w matches any “word” character (letters, digits, and underscores).
  • \W matches any non-word character.
  • \s matches any whitespace character (spaces, tabs, etc.).
  • \S matches any non-whitespace character.

Simple Regular Expression Examples in JavaScript

Let’s apply some of these concepts with a few simple examples to validate form inputs.

Example 1: Validating an Email Address

To check if a user’s email input follows a basic format (e.g., example@domain.com), we can use a regex pattern that captures the most common structure of an email address.

let emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
let email = "test@example.com";
console.log(emailPattern.test(email)); // true if valid, false if not

This pattern:

  • Starts with ^ and ends with $ to match the entire string.
  • Allows letters, numbers, and certain special characters before the “@”.
  • Requires an “@” symbol, followed by more letters/numbers and a dot.
  • Ends with a two-letter or more domain suffix (like .com or .org).

Example 2: Validating a Phone Number

To check for a 10-digit phone number, we might use:

let phonePattern = /^\d{10}$/;
let phone = "1234567890";
console.log(phonePattern.test(phone)); // true if valid, false if not

^\d{10}$ matches exactly 10 digits, with no other characters allowed. This would reject numbers with spaces or dashes, enforcing a very strict format.

How to Use Regular Expressions in JavaScript Validation

To validate form fields with regular expressions, JavaScript provides methods that make this process straightforward:

Using .test() Method

The .test() method checks if a string matches a regex pattern, returning true or false. This is ideal for validation:

let pattern = /^[a-zA-Z]{2,}$/; // Example: only letters, minimum 2 characters
let name = document.getElementById("name").value;
if (!pattern.test(name)) {
alert("Please enter a valid name.");
return false;
}

Using .match() Method

The .match() method returns an array of matched results or null if no match is found. While not commonly used for form validation, it’s helpful when extracting information from input fields.

Implementing in Event Handlers

You can tie regex validation to form events like onblur or onsubmit to validate inputs at specific times:

HTML:

<input type="text" id="email" onblur="validateEmail()">

JavaScript:

function validateEmail() {
let email = document.getElementById("email").value;
let emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailPattern.test(email)) {
alert("Please enter a valid email address.");
}
}

Practical Tips for Using Regular Expressions

  • Start Simple: For beginners, it’s best to start with basic patterns and gradually add complexity. Try to understand each part of the pattern rather than using it blindly.
  • Use Online Tools: Regex tools, like regex101.com, can help visualize patterns, explain each part, and test them against example strings.
  • Break Down Complex Patterns: If a regex pattern feels too complex, break it down into smaller parts, or start with a simpler version and add components as needed.


RegEx Form Validation

In this section, we’ll apply regular expressions (regex) to specific types of input fields commonly used in web forms. By creating validation patterns for fields like email addresses, phone numbers, postal codes, and passwords, we can ensure that users enter data in the required formats. Understanding and applying these patterns effectively is key to building reliable and user-friendly forms.

Implementing Pattern Matching for Form Fields

Regular expressions allow us to enforce specific formats on user input. For each input type, we’ll cover common validation patterns and discuss the elements used to build them.

Examples of Basic Patterns for Common Input Types

Let’s look at specific examples for different types of fields and explain how each pattern works in detail.

Example 1: Email Format Validation

Email validation is one of the most frequent uses of regular expressions. A basic email regex pattern ensures that the input follows a structure like user@example.com. While it’s possible to create very complex patterns for email validation, we’ll use a simpler pattern that covers most common cases:

let emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
let email = document.getElementById("email").value;
if (!emailPattern.test(email)) {
alert("Please enter a valid email address.");
return false;
}

Explanation:

  • ^ and $  – These anchors ensure the pattern matches the entire string from start to end.
  • [a-zA-Z0-9._%+-]+  – The first part of an email allows letters, numbers, and some special characters (._%+-). The + sign means “one or more occurrences.”
  • @  – Matches the “@” symbol, which is required in all email addresses.
  • [a-zA-Z0-9.-]+   Matches the domain part (e.g., example in example.com), which can contain letters, numbers, dots, and hyphens.
  • \.   Escapes the period, making it a literal dot rather than any character.
  • [a-zA-Z]{2,}   Matches the domain extension (e.g., .com, .org). {2,} requires at least two letters, allowing for longer extensions like .info.

This pattern will validate most standard email formats without getting overly complex.

Example 2: Phone Number Format

Phone numbers can vary widely in format, but let’s start with a common North American pattern for 10-digit phone numbers, often displayed as (123) 456-7890 or 123-456-7890. Here’s a regex pattern that covers these cases:

let phonePattern = /^(\(\d{3}\)|\d{3})[- ]?\d{3}[- ]?\d{4}$/;
let phone = document.getElementById("phone").value;
if (!phonePattern.test(phone)) {
alert("Please enter a valid phone number.");
return false;
}

Explanation:

  • ^ and $  – Match the entire string from start to end.
  • (\(\d{3}\)|\d{3})   Allows either a 3-digit area code in parentheses (e.g., (123)) or just the 3 digits without parentheses.
  • [- ]?  – Matches a dash or space after the area code, but it’s optional (? allows zero or one occurrence).
  • \d{3}  – Matches the next three digits of the phone number.
  • [- ]?  – Optionally matches a dash or space between the second and third sections.
  • \d{4}  Matches the final four digits of the phone number.

This pattern covers several common U.S. phone number formats and provides flexibility for users entering their numbers.

Example 3: Postal Code Validation

Let’s create a pattern for U.S. postal codes (ZIP codes), which can be either a 5-digit number (e.g., 12345) or a 9-digit number with a hyphen (e.g., 12345-6789).

let zipPattern = /^\d{5}(-\d{4})?$/;
let zip = document.getElementById("zip").value;
if (!zipPattern.test(zip)) {
alert("Please enter a valid ZIP code.");
return false;
}

Explanation:

  • ^ and $  – Match the entire string from start to end.
  • \d{5}  – Matches exactly five digits.
  • (-\d{4})?  – Optionally matches a hyphen followed by exactly four digits (? allows zero or one occurrence of this group).

This pattern ensures that ZIP codes are in either the 5-digit or 9-digit format.

Example 4: Password Strength Validation

To ensure that passwords are both secure and easy to remember, we often require passwords to meet specific criteria. Here’s a pattern that enforces a minimum of eight characters, at least one uppercase letter, one lowercase letter, one digit, and one special character:

let passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;
let password = document.getElementById("password").value;
if (!passwordPattern.test(password)) {
alert("Password must be at least 8 characters long and include an uppercase letter, a lowercase letter, a digit, and a special character.");
return false;
}

Explanation:

  • ^ and $  – Match the entire string from start to end.
  • (?=.*[a-z])  – Positive lookahead to ensure at least one lowercase letter is present.
  • (?=.*[A-Z])  – Positive lookahead to ensure at least one uppercase letter is present.
  • (?=.*\d)  –  Positive lookahead to ensure at least one digit is present.
  • (?=.*[!@#$%^&*])  – Positive lookahead to ensure at least one special character is present.
  • [A-Za-z\d!@#$%^&*]{8,}  – Ensures the entire password is at least 8 characters long and only includes letters, numbers, and specified special characters.

This pattern helps ensure that passwords meet common security requirements, enhancing both security and user experience.

Building and Testing Form Validation Scripts

With regular expressions in place, we can now create form validation scripts that combine multiple checks, providing comprehensive validation. Here’s an example of a full validation function for a registration form that checks several fields:

function validateForm() {
let emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
let phonePattern = /^(\(\d{3}\)|\d{3})[- ]?\d{3}[- ]?\d{4}$/;
let zipPattern = /^\d{5}(-\d{4})?$/;
let passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;

let email = document.getElementById("email").value;
let phone = document.getElementById("phone").value;
let zip = document.getElementById("zip").value;
let password = document.getElementById("password").value;

if (!emailPattern.test(email)) {
alert("Please enter a valid email address.");
return false;
}
if (!phonePattern.test(phone)) {
alert("Please enter a valid phone number.");
return false;
}
if (!zipPattern.test(zip)) {
alert("Please enter a valid ZIP code.");
return false;
}
if (!passwordPattern.test(password)) {
alert("Password must be at least 8 characters long and include an uppercase letter, a lowercase letter, a digit, and a special character.");
return false;
}
return true; // All validations passed
}

This validateForm function can be linked to a form’s onsubmit event to perform all checks before submission, ensuring that each input meets the required format.



Building a Validated Form

Now that we’ve covered various validation techniques and regular expressions for form fields, it’s time to put it all together. In this section, we’ll focus on building a comprehensive form validation script that checks multiple fields, prevents form submission if any data is invalid, and provides clear feedback for the user. Finally, we’ll discuss how to test validation scripts effectively to ensure they work as expected.

Putting It All Together: Creating a Sample Form with Validation

To demonstrate complete form validation, we’ll build a sample form with fields for name, email, phone number, ZIP code, and password. Our goal is to validate each of these fields, displaying appropriate error messages and only allowing the form to submit if all validations pass.

HTML Structure of the Sample Form

Here’s the HTML structure for our form. Each field has an associated span element to display validation messages next to the input field.

<form id="registrationForm" onsubmit="return validateForm()">
<label>Name: <input type="text" id="name"></label>
<span id="nameError" class="error"></span><br>

<label>Email: <input type="text" id="email"></label>
<span id="emailError" class="error"></span><br>

<label>Phone: <input type="text" id="phone"></label>
<span id="phoneError" class="error"></span><br>

<label>ZIP Code: <input type="text" id="zip"></label>
<span id="zipError" class="error"></span><br>

<label>Password: <input type="password" id="password"></label>
<span id="passwordError" class="error"></span><br>

<button type="submit">Submit</button>
</form>

Each input element has an id so it can be accessed in JavaScript, and each error span is assigned an id to display validation feedback.

Writing the Validation Script

The validation function, validateForm, will check each input field. If a field’s input is invalid, we’ll display a message in its corresponding error span element and stop the form submission.

Here’s the full JavaScript function for validation:

function validateForm() {
let isValid = true;

// Validation patterns
let namePattern = /^[a-zA-Z\s]{2,}$/; // At least 2 characters, letters and spaces only
let emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
let phonePattern = /^(\(\d{3}\)|\d{3})[- ]?\d{3}[- ]?\d{4}$/;
let zipPattern = /^\d{5}(-\d{4})?$/;
let passwordPattern = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/;

// Validate name
let name = document.getElementById("name").value;
if (!namePattern.test(name)) {
document.getElementById("nameError").textContent = "Please enter a valid name (letters and spaces only).";
isValid = false;
} else {
document.getElementById("nameError").textContent = "";
}

// Validate email
let email = document.getElementById("email").value;
if (!emailPattern.test(email)) {
document.getElementById("emailError").textContent = "Please enter a valid email address.";
isValid = false;
} else {
document.getElementById("emailError").textContent = "";
}

// Validate phone
let phone = document.getElementById("phone").value;
if (!phonePattern.test(phone)) {
document.getElementById("phoneError").textContent = "Please enter a valid phone number.";
isValid = false;
} else {
document.getElementById("phoneError").textContent = "";
}

// Validate ZIP code
let zip = document.getElementById("zip").value;
if (!zipPattern.test(zip)) {
document.getElementById("zipError").textContent = "Please enter a valid ZIP code.";
isValid = false;
} else {
document.getElementById("zipError").textContent = "";
}

// Validate password
let password = document.getElementById("password").value;
if (!passwordPattern.test(password)) {
document.getElementById("passwordError").textContent = "Password must be at least 8 characters
long and include an uppercase letter, a lowercase letter, a digit, and a special character.";
isValid = false;
} else {
document.getElementById("passwordError").textContent = "";
}

// Prevent form submission if there are validation errors
return isValid;
}

Explanation:

  • We start by setting isValid to true. If any validation fails, isValid is set to false, preventing form submission.
  • Each field’s value is tested against a regex pattern. If the input fails, an error message is displayed in the span element next to the field.
  • If a field passes validation, we clear any error message for that field.

By linking this function to the onsubmit event in the form, the function will run every time the form is submitted, and it will only allow submission if all fields are valid.

Debugging and Testing Validation Code

Testing form validation code thoroughly ensures it behaves as expected across various cases. Here are some best practices for testing:

Test Valid and Invalid Cases for Each Field:

  • For each field, try both valid and invalid inputs to confirm that the validation rules are applied correctly.
  • Example: For the email field, try a correctly formatted email (user@example.com) and common invalid formats (e.g., “user@domain”, “user@.com”).

Check Boundary Conditions:

  • For numeric fields, test edge cases like 0 and negative numbers if they’re allowed.
  • For text fields with minimum length requirements, test strings right at the boundary, like a 7-character password if the minimum is 8.

Use Console Logs for Debugging:

  • During development, add console.log statements in the validation function to check field values or the results of regex tests.
  • Example: console.log("Phone validation passed:", phonePattern.test(phone));

Simulate User Errors:

  • Try leaving fields blank, entering random characters, or using formats that users might mistakenly enter. This helps ensure that your form handles typical user errors gracefully.

Ensure Error Messages Are Clear and Accurate:

  • Error messages should be specific enough that users know how to correct their input. Avoid generic messages like “Invalid input” and instead specify the exact requirement, e.g., “Please enter a 10-digit phone number.”

Test in Multiple Browsers:

  • JavaScript and form behavior can vary across browsers, so test your form in major browsers (e.g., Chrome, Firefox, Safari, Edge) to ensure consistent behavior.

Consider Accessibility:

  • Use aria-live attributes on error messages to announce validation errors to screen readers, making your form more accessible.

Best Practices for Form Validation in JavaScript

To ensure your validation code is robust, keep these best practices in mind:

  • Keep Validation Simple and Focused: Avoid overly complex patterns or rules that could confuse users or prevent legitimate data entry.
  • Provide Immediate Feedback: Display validation messages close to the input field rather than waiting until the form is submitted.
  • Use Consistent Styling for Errors: Apply CSS to style error messages or fields consistently, making it easy for users to recognize issues.
  • Avoid Over-Reliance on Client-Side Validation: While client-side validation improves usability, always validate data on the server side to ensure security and data integrity.
  • Create Reusable Validation Functions: If your application has multiple forms, consider creating generic functions for common validations, like email or phone number checks, to avoid duplicate code.


"Cheat Code" for RegEx

It's good to learn about regular expression syntax.  However, in the spirit of “we can't be an expert in everything”, it's good to remember that AI models like ChatGPT are generally very good at writing RegEx patterns based on a thorough description. So if you just need a pattern defined, and you are stumped about how to put it together, I think these resources are a great place to turn. In fact, I regularly use them myself as part of my coding toolset.

Videos for Module 8 - Strings, Validation and Regular Expressions

There are no videos yet this term for this Module. Check back soon!