Form validation using javascript
Tags: beginners, javascript, tutorial, webdev
Published: 2021-10-31 13:51:03

Working with forms is an every day task for almost every web developer. No matter what site you'll create it will use forms. Validating the form data on the client side is a nice-to-have feature when it comes to user experience. In this tutorial we'll create a simple form validation using javascript.

While client-side form validation gives a nice user experience, it can be tricked and bypassed really easily. To prevent malicious use, **you should always validate form data on the server side**
## Video Tutorial
If you would watch a detailed step-by-step video instead you can check out the video I made covering this project on [my Youtube Channel](https://www.youtube.com/c/JavaScriptAcademyOfficial):

{% youtube CYlNJpltjMM %}

## HTML
Let's start with the HTML markup. We'll have a `container` div, that we'll use to position and style our form. Inside that, not surprisingly, we'll create a `form`, we also set an `id` for it, and set the `action` to `/` since we don't really want to submit this form.

We'll create four input fields, for the username, email, password, and password confirmation. For styling and control purposes we'll wrap these `input` tags into `div`s with the class `input control`. Each of these input controls will contain a `label`, an `input`, and a `div` with the class `error`. Every input should have an id and name attribute. The label's should have a matching `for` property with the corresponding input tag's name attribute. For the input type we will use `text` for the username and email, and use `password` for the password and the password confirmation. The div with the `error` class will hold the error messages for the specific input field. It will be empty for now, we will modify it from javascript.

Lastly, we have to add a button to "submit" our form. In this example we won't really submit the form just simulate it. For the submit button I'll use a button with a type of `submit`.
```html
<div class="container">
        <form id="form" action="/">
            <h1>Registration</h1>
            <div class="input-control">
                <label for="username">Username</label>
                <input id="username" name="username" type="text">
                <div class="error"></div>
            </div>
            <div class="input-control">
                <label for="email">Email</label>
                <input id="email" name="email" type="text">
                <div class="error"></div>
            </div>
            <div class="input-control">
                <label for="password">Password</label>
                <input id="password"name="password" type="password">
                <div class="error"></div>
            </div>
            <div class="input-control">
                <label for="password2">Password again</label>
                <input id="password2"name="password2" type="password">
                <div class="error"></div>
            </div>
            <button type="submit">Sign Up</button>
        </form>
    </div>
```

That is the HTML markup that we need for our form. Let's style it a bit with CSS.

## CSS
We'll give a simple clean spacious design for this tutorial. I'll set a linear gradient as the background and I'll use a custom google font, that you can [install from here.](https://fonts.google.com/specimen/Poppins)
```css
body {
    background: linear-gradient(to right, #0f2027, #203a43, #2c5364);
    font-family: 'Poppins', sans-serif;
}
```
We'll give a fix width to our form, and center it with margins, also I'll give it a top margin to move it down a bit vertically. To have more space we apply 20px of padding. We'll set a fixed font size, a light background color and also set a border radius to have rounded corners.
```css
#form {
    width: 300px;
    margin: 20vh auto 0 auto;
    padding: 20px;
    background-color: whitesmoke;
    border-radius: 4px;
    font-size: 12px;
}
```
For the form title, we'll use a dark text color, and center it horizontally using `text-align: center`. The submit button should stand out so we'll use a blue background color, and white text color. We also remove the browser default borders and give it a little border-radius. We'll give it a little spacing with paddings and margins, and make it full-width by applying 100% width.
```css
#form h1 {
    color: #0f2027;
    text-align: center;
}

#form button {
    padding: 10px;
    margin-top: 10px;
    width: 100%;
    color: white;
    background-color: rgb(41, 57, 194);
    border: none;
    border-radius: 4px;
}
```
To have the inputs stacked below each other we'll use flexbox. To do that we'll set `display: flex;` and `flex-direction: column`. For the inputs we'll set a grey border, with a little border-radius. We'll set the display property to `block`, and make them full-width, by applying width 100%. We'll also set a little padding, so it'll be more spacious. I'll also remove the outline when the input is in focus, by setting `outline: 0`.
```css
.input-control {
    display: flex;
    flex-direction: column;
}

.input-control input {
    border: 2px solid #f0f0f0;
    border-radius: 4px;
    display: block;
    font-size: 12px;
    padding: 10px;
    width: 100%;
}

.input-control input:focus {
    outline: 0;
}
```
We'll use two classes ("success" and "error") to give visual feedback to the user on whether the input's value is valid or not. We'll apply these classes from javascript to the input-control div which contains the specific input field. When the success class is present we will set a green border color, otherwise if error is present we'll use a red border color instead. For the error div we'll use a smaller font-size and a red color to show the error messages.
```css
.input-control.success input {
    border-color: #09c372;
}

.input-control.error input {
    border-color: #ff3860;
}

.input-control .error {
    color: #ff3860;
    font-size: 9px;
    height: 13px;
}
```
Let's do the validation in javascript next!
## Javascript
The first thing we have to do is to save references for the form, and the input fields. As we gave id for every input and the form we can easily to do by using `getElementById`.
```js
const form = document.getElementById('form');
const username = document.getElementById('username');
const email = document.getElementById('email');
const password = document.getElementById('password');
const password2 = document.getElementById('password2');
```
To prevent the form for automatically submit we have to attach and event listener to our form's `submit` event. In this event handler function we have to call `preventDefault()` function to prevent the form from submitting automatically. Instead of submitting we'll call the `validateInputs` function, which will validate the inputs and if we want to we can submit the form in there after every check passes, but we won't do that in this tutorial. We'll create this `validateInputs` shortly.
```js
form.addEventListener('submit', e => {
    e.preventDefault();

    validateInputs();
});
```
We'll also create two helper functions: `setError`, `setSuccess`. We'll use these helper functions to set the error or success states of the input controls. Let's start with the setError one. It receives two parameters: `element`, and `message`. The element will be the input element that is in the specific input-control. So first we have to get the input control parent div. We'll save it into the `inputControl` variable, and get the input control div by using the `parent` property of the input element. Next we have to gather the error div, and save it into a variable. We can do that by querying the input control with the error class.
Now we have to set the error div's innerText to be the message that we got in parameters, and remove the `success` class from the input control (if it exists) and add the error class.
```js
const setError = (element, message) => {
    const inputControl = element.parentElement;
    const errorDisplay = inputControl.querySelector('.error');

    errorDisplay.innerText = message;
    inputControl.classList.add('error');
    inputControl.classList.remove('success')
}
```
The setSuccess method will be really similar. The first difference is that it won't receive a message as a parameter. We have to clear the error display by setting its innerText to an empty string. Lastly we have to reverse the class application. We'll add the `success` class to the inputControl and remove the `error` class (if present).
```js
const setSuccess = element => {
    const inputControl = element.parentElement;
    const errorDisplay = inputControl.querySelector('.error');

    errorDisplay.innerText = '';
    inputControl.classList.add('success');
    inputControl.classList.remove('error');
};
```
We will create one last helper function to validate emails. This is an optional step, if you don't want to use regular expressions, feel free to just set the input type of the email field to `email`. The `isValidEmail` function will take a string as a parameter and use this weird looking regular expression to check whether it is a valid email or not. We'll use `String.test()` function to test the string against the regex. We'll also convert the email to a string and make it lowercase.
```js
const isValidEmail = email => {
    const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
}
```
Now we should create the validator `validateInputs` function. First we will get the value of all the input fields. We can do that by getting the value property's value of the input field references. We'll call the `String.trim()` function to remove the trailing empty spaces (if any) from the start and end of the values.
Then we can start validating inputs. We'll use `if, else` statements to do the validation. For the username we will check whether if it is empty or not, by comparing the value with an empty string. If it empty, we'll call the `setError` function and provide the username element to it, with our error message. Otherwise we'll call the `setSuccess` method with the username element. Now we have to do this for the other input fields, but the approach will be the same.
```js
const validateInputs = () => {
    const usernameValue = username.value.trim();
    const emailValue = email.value.trim();
    const passwordValue = password.value.trim();
    const password2Value = password2.value.trim();

    if(usernameValue === '') {
        setError(username, 'Username is required');
    } else {
        setSuccess(username);
    }
};
```
For the email we'll check if it is provided or not, and set an error if it is empty. If it is not empty we'll check whether it is a valid email address, and if not we'll set an error, otherwise we set success for the field.
```js
if(emailValue === '') {
        setError(email, 'Email is required');
    } else if (!isValidEmail(emailValue)) {
        setError(email, 'Provide a valid email address');
    } else {
        setSuccess(email);
    }
}
```
For the password we'll check whether it is empty or not, and if it is not empty we'll check if it is longer than 7 characters. If not, well set an error, otherwise we'll set it as success.
```js
if(passwordValue === '') {
        setError(password, 'Password is required');
    } else if (passwordValue.length < 8 ) {
        setError(password, 'Password must be at least 8 character.')
    } else {
        setSuccess(password);
    }
}
```
For the password confirmation we'll check if it is empty, and we should also check if the password confirmation's value is equal to the password's value.
```js
if(password2Value === '') {
        setError(password2, 'Please confirm your password');
    } else if (password2Value !== passwordValue) {
        setError(password2, "Passwords doesn't match");
    } else {
        setSuccess(password2);
    }
}
```
Now we have every input validated, if we wanted to we could submit our form now to a specific endpoint.

Good job now you have a working form validation Javascript. Please note that you always have to validate the form inputs on the server-side as client-side validation can be easily bypassed. There are way more advanced form validation methods and libraries that we use in modern web development, but this project is a really good way to start and learn the fundamentals.
## Where you can learn more from me?
I create education content covering web-development on several platforms, feel free to 👀 check them out.

I also create a newsletter where I share the week's or 2 week's educational content that I created. No bull💩 just educational content.

🔗 Links:
* 🍺 Support free education and [buy me a beer](https://ko-fi.com/adamnagy)
* 💬 Join our [community on Discord](https://discord.gg/GuxmcEgAjB)
* 📧 Newsletter [Subscribe here](https://www.getrevue.co/profile/dev_adamnagy)
* 🎥 YouTube [Javascript Academy](https://www.youtube.com/channel/UCicOwFWkuMX0ddFaKCc_E5Q)
* 🐦 Twitter: [@dev_adamnagy](https://twitter.com/dev_adamnagy)
* 📷 Instagram [@javascriptacademy](https://www.instagram.com/javascriptacademy/)