DEV Community

Cover image for Form Validation with JavaScript
Tracy | Software Engineer
Tracy | Software Engineer

Posted on

Form Validation with JavaScript

Before submitting data to the server, It is important to ensure all required form controls are filled out, in the correct format. This is called client-side form validation and helps ensure data submitted matches the requirements set forth in the various form controls.

HTML Validation

Although validation can also be done with HTML attributes like - required, minlength, maxlength, min, max, type, and pattern. The downside of it is that you can't customize it to fit your requirements.

What is Form Validation?

Have you ever tried to sign up on a website where they had certain requirements? Like:

  • Ensuring your password is between 8 to 30 characters or making sure your password is mixed between letters, numbers, and asterisks.
  • Or ensure you include the @ for the email input field by popping messages like "Please enter a valid email address".
  • "This field is required" (You can't leave this field blank)

This is called Validation. When you enter your details on a form website, the browser and/or the web server will check to see that the data is in the correct format and within the constraints set by the application.

Form validation is the process of verifying that the data entered into an HTML form is accurate, complete, and meets the specified criteria before it is submitted to the server.

The application allows the data to be submitted to the server if the information is correctly formatted. If the information is not correctly formatted, it gives the user an error message explaining what needs to be corrected.

Building A Form

Let's build a form webpage in order to solidify our understanding of form validation.

The HTML Code

<div class="formContainer">
        <header>
            <h1>Sign In</h1>
            <a href="test1.html">CHECK</a>
        </header>

        <form id="myForm">
            <div class="formDetails">
                <label for="name">Name:</label>
                <input type="text" id="name" name="name">
                <div class="errorMessage"></div>
            </div>

            <div class="formDetails">
                <label for="email">Email:</label>
                <input type="email" id="email" name="email">
                <div class="errorMessage"></div>
            </div>

            <div class="formDetails">
                <label for="password">Password:</label>
                <input type="password" id="password" name="password">
                <div class="errorMessage"></div>
            </div>

            <div class="formDetails">
                <label for="confirmpassword">Confirm Password:</label>
                <input type="password" id="confirmPassword" name="confirmpassword">
                <div class="errorMessage"></div>
            </div>

            <button id="button" type="submit">Submit</button>
          </form>
    </div>
Enter fullscreen mode Exit fullscreen mode
  • The HTML code defines a form with four input fields: name, email, password, and confirm password. Each input field is wrapped in a div element with a class of formDetails.
  • Below each input field, there is a div element with a class of errorMessage. This is where any error messages related to the corresponding input field will be displayed.
  • The form also has a submit button with an id of button. This button triggers the form submission when clicked.

The CSS Code

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body{
    background-color: #021012;
    font-family: sans-serif;
}

.formContainer{
    width: 80%;
    height: 85vh;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    background-color: #E2F4FD;
}
header{
    text-align: center;
    margin: 2rem 0;
    font-weight: 600;
}

#myForm{
    width: 90%;
    margin: 1rem auto;
}

.formDetails{
    margin: 1rem 0;
}

label{
    display: block;
    font-size: 1rem;
    font-weight: 600;
    margin-bottom: .4rem;
}

input{
    width: 100%;
    padding: .6rem 0;
    outline: none;
    font-size: 1rem;
}

input:focus{
    outline: 1px solid #064247;
}
button{
    margin: 1.1rem 0;
    background-color: #053135;
    color: #fff;
    font-weight: 600;
    border: none;
    padding: .8rem 0;
    width: 100%;
}
.errorMessage{
    margin-top: .3rem;
    font-size: .9rem;
    font-weight: 600;
    font-family: monospace;
}
.formDetails.success input {
    border-color: #09c372;
    outline: none;
  }

  .formDetails.error input {
    border-color: #f2070e;
  }

@media screen and (min-width: 1024px) {
    .formContainer{
        width: 30%;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • The .formContainer selector sets the width of the form container to 80% of the parent element, and the height to 85% of the viewport height, and positions it in the center of the screen using absolute positioning and the transform property - transform: translate(-50%, -50%). The background color is set to a light shade of blue - #021012.
  • The input and button selectors set the width to 100% of the parent container, padding to 0.6rem at the top and bottom of the input selector, outline to none, and font size to 1rem. There is also a focus state added to the input selector that outlines the input with a 1px solid border in a different color.
  • The .formDetails.success input selector applies the styles to the input element when the .formDetails container has a class of success. It sets the border color to a light shade of green and the outline to none.
  • The .formDetails.error input selector applies the styles to the input element when the .formDetails container has a class of error. It sets the border color to a dark shade of red.
@media screen and (min-width: 1024px) {
    .formContainer{
        width: 30%;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • The @media rule creates a media query that applies styles when the screen width is above 1024px. In this case, the width of the .formContainer is set to 30% of the parent element. This makes the form container smaller when viewed on larger screens.

JavaScript For Validation

  • The code listens for the form submission event and prevents the form from submitting by default. It then performs validations on each input field and displays appropriate error messages in the errorMessage divs and applies the success and error classes to the parent formDetails divs based on the validation result.
const myForm = document.getElementById('myForm');
myForm.addEventListener('submit', (event) => {
    event.preventDefault(); 
}
Enter fullscreen mode Exit fullscreen mode
  • For each input field, the code first gets the input value and trims any whitespace. It then gets the corresponding errorMessage div and input element using the querySelector method. If the input value is empty, the code sets the error message to a relevant message and applies the error class to the parent formDetails div. If the input value is not empty, the code clears the error message and applies the success class to the parent formDetails div.
const name = myForm.elements.name.value.trim();
const nameError = document.querySelector('#name + .errorMessage');
const nameInput = document.getElementById('name');
if (name === '') {
    nameError.textContent = 'Name is required.';
      nameInput.parentNode.classList.add('error');
      nameInput.parentNode.classList.remove('success');
    } else {
      nameError.textContent = '';
      nameInput.parentNode.classList.add('success');
      nameInput.parentNode.classList.remove('error');
    }
Enter fullscreen mode Exit fullscreen mode
  • For the email input field, the code also checks if the email is in a valid format using a regular expression. If the email is invalid, the code sets the error message to a relevant message and applies the error class to the parent formDetails div.
const email = myForm.elements.email.value.trim();
    const emailError = document.querySelector('#email + .errorMessage');
    const emailInput = document.getElementById('email');
    if (email === '') {
      emailError.textContent = 'Email is required.';
      emailInput.parentNode.classList.add('error');
      emailInput.parentNode.classList.remove('success');
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      emailError.textContent = 'Please enter a valid email address.';
      emailInput.parentNode.classList.add('error');
      emailInput.parentNode.classList.remove('success');
    } else {
      emailError.textContent = '';
      emailInput.parentNode.classList.add('success');
      emailInput.parentNode.classList.remove('error');
    }
Enter fullscreen mode Exit fullscreen mode
  • For the password input field, the code also checks if the password is at least 8 characters long. If the password is less than 8 characters, the code sets the error message to a relevant message and applies the error class to the parent formDetails div.
const password = myForm.elements.password.value.trim();
    const passwordError = document.querySelector('#password + .errorMessage');
    const passwordInput = document.getElementById('password');
    if (password === '') {
      passwordError.textContent = 'Password is required.';
      passwordInput.parentNode.classList.add('error');
      passwordInput.parentNode.classList.remove('success');
    } else if (password.length < 8) {
      passwordError.textContent = 'Password is expected to be 8 characters.';
      passwordInput.parentNode.classList.add('error');
      passwordInput.parentNode.classList.remove('success');
    } else {
      passwordError.textContent = '';
      passwordInput.parentNode.classList.add('success');
      passwordInput.parentNode.classList.remove('error');
    }
Enter fullscreen mode Exit fullscreen mode
  • For the confirm password input field, the code also checks if the confirm password matches the password. If the confirm password does not match, the code sets the error message to a relevant message and applies the error class to the parent formDetails div.
const confirmPassword = myForm.elements.confirmpassword.value.trim();
    const confirmPasswordError = document.querySelector('#confirmPassword + .errorMessage');
    const confirmPasswordInput = document.getElementById('confirmPassword');
    if (confirmPassword === '') {
      confirmPasswordError.textContent = 'Confirm Password is required.';
      confirmPasswordInput.parentNode.classList.add('error');
      confirmPasswordInput.parentNode.classList.remove('success');
    } else if (confirmPassword !== password) {
      confirmPasswordError.textContent = 'Passwords do not match.';
      confirmPasswordInput.parentNode.classList.add('error');
      confirmPasswordInput.parentNode.classList.remove('success');
    } else {
      confirmPasswordError.textContent = '';
      confirmPasswordInput.parentNode.classList.add('success');
      confirmPasswordInput.parentNode.classList.remove('error');
    }
Enter fullscreen mode Exit fullscreen mode
  • In the final step, the code checks if there are any error messages displayed. If there are no error messages, the code submits the form. Otherwise, it prevents the form from submitting.
if (nameError.textContent === '' && emailError.textContent === '' && passwordError.textContent === '' && confirmPasswordError.textContent === '') {
        myForm.submit();
      }
    });
Enter fullscreen mode Exit fullscreen mode

The Final Result

Check it out on Codepen

If you found this article helpful, please ensure you follow for more helpful posts. I would also appreciate your ideas on what you would be interested in learning,

Top comments (5)

Collapse
 
duynam77186 profile image
Duy Nam VO

It works but that approach will be unmaintainable very quickly.

What I would first do it is to offload the validation to a library (first rule of securty is that you don't want to implement your own), Joi and Joi password are good choices.

Secondly (that's more of a personal preference, and a bit overkill for your example) I would use MVVM approach for a form that is going to scale better on the long run. MVVM, that's a microsoft implementation but a JS implementation shouldn't too hard.

Collapse
 
tracy4code profile image
Tracy | Software Engineer

Thanks for sharing this method.

Collapse
 
crayoncode profile image
crayoncode

Keep in mind that this is purely client-sided which is a good approach for catching a few validation errors without making a server round-trip. However, it is a good/necessary practice to enforce these rules on the server side regardless of what is implemented in the client to make it effective and secure.

Collapse
 
manvendrask profile image
Manvendra Singh

How is this even relevant in current state of technology? It is an old school practice.

Collapse
 
tracy4code profile image
Tracy | Software Engineer

It is still relevant to the client side to prevent users from submitting the wrong requirements to the browser.