Simple HTML, TAILWINDCSS & Javascript Form Validation
Tags: javascript, tailwindcss, html, css
Published: 2022-03-24 23:42:29

In this simple tutorial, i am going to share a complete guide in creating a simple advanced validation form.

## **Why did i use JS/Why i do**

I love using javascript alot since am a full stack web developer. I only use it in any type of application developemnt and it just works like magic to me.
I recenly started using tailwindcss but in this tutorial, i did not take my time working on so much styling but the code on my [github account](https://github.com/elvis-sautet/simple-form-validation) will be updated and added more functionalities as time goes by.

## The Html code:

```HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.tailwindcss.com"></script>
	
	<link rel="stylesheet" href="./index.css">
    <title>FORM VALIDATION</title>
  </head>
  <body>
    <div
      class="min-h-screen bg-slate-900 min-h-screen flex items-center justify-center"
    >
      <div
        class="backdrop-blur-sm bg-white/80 p-5 max-w-md w-full rounded-md shadow-white/10 shadow-sm"
      >
        <form
		id="login"
          class="text-black text-md flex flex-col space-y-3"
          autocomplete="off"
        >
          <div class="flex flex-col w-full space-y-3 tracking-wide">
            <label class="text-lg tracking-wide font-mono" 
			for="firstName"></label>
              First Name</label
            >
            <input
              type="text"
              name="firstName"
              id="firstName"
              class="border-2 firstName w-full p-2 rounded-lg focus:outine-none focus:outline-none"
              autocomplete="off"
              aria-autocomplete="off"
            />
			<span class="block firstNameError text-red-500 text-xs hidden">error</span>
          </div>
          <div lass="flex flex-col w-full space-y-3 tracking-wide">
            <label class="text-lg tracking-wide font-mono" for="firstName">
              Last Name</label
            >
            <input
              type="text"
              name="lastName"
              id="lastName"
              class="border-2 lastName w-full p-2 rounded-lg focus:outine-none focus:outline-none"
              autocomplete="off"
            />
			<span class="block lastNameError text-red-500 text-xs hidden">error</span>
          </div>
          <div lass="flex flex-col w-full space-y-3 tracking-wide">
            <label  class="text-lg tracking-wide font-mono" for="email"> Your Email</label>
            <input
              type="text"
              name="email"
              id="email"
              class="border-2 email w-full p-2 rounded-lg focus:outine-none focus:outline-none"
              autocomplete="off"
            />
			<span class="block emailError text-red-500 text-xs  hidden">error</span>
          </div>
          <div class="">
            <input value="Login Now" type="submit" id="btn" class="px-4 py-3 mt-5 rounded-md bg-slate-600 w-full text-white tracking-wide transition-all duration-300 ease-in-out hover:bg-slate-900 
			cursor-pointer disabled:cursor-not-allowed disabled:opacity-20"/>
			
          </div>
        </form>
      </div>
    </div>
	    <script  src="./index.js"></script>

  </body>
</html>

```

## The Javascript Code:

```javascript
const firstNameInput = document.getElementById("firstName");
const lastNameInput = document.getElementById("lastName");
const emailInput = document.getElementById("email");
const buttonSubmit = document.getElementById("btn");
const form = document.getElementById("login");
const firstNameError = document.getElementsByClassName("firstNameError")[0];
const lastNameError = document.getElementsByClassName("lastNameError")[0];
const emailError = document.getElementsByClassName("emailError")[0];

//define and declare and empty errors object
let error = {};

/* This is a JavaScript event listener. It is a way to listen for an event. In this case, it is
listening for the form to be submitted. */
form.addEventListener("submit", function (e) {
  e.preventDefault();
//function to validate the form fields before submitting
  checkEmpty();
});

// validate empty fields and set error object
function checkEmpty() {
  //loop and remove all key and value fields in the errors object
  for (let key in error) {
    delete error[key];
  }
  //set all in firstname, lastname, email spans to display none
  firstNameError.style.display = "none";
  lastNameError.style.display = "none";
  emailError.style.display = "none";

  //remove all the error class "border-red-500 classes"
  firstNameInput.classList.remove("border-red-500");
  lastNameInput.classList.remove("border-red-500");
  emailInput.classList.remove("border-red-500");

//remove white spaces from every input Field
  const firstNameValue = firstNameInput.value.trim();
  const lastNameValue = lastNameInput.value.trim();
  const emailValue = emailInput.value.trim();

  //check if all inputs are empty then add new new error keys to the defined error object
  if (firstNameValue === "") {
    error.firstName = "First Name is required";
  }
  if (lastNameValue === "") {
    error.lastName = "Last Name is required";
  }
  if (emailValue === "") {
    error.email = "Email is required";
  }

  //validate the inputs firstName and lastName
  if (firstNameValue !== "") {
    if (!firstNameValue.match(/^[a-zA-Z0-9]+$/)) {
      error.firstName = "First Name must be letters only";
    }
  }
  if (lastNameValue !== "") {
    if (!lastNameValue.match(/^[a-zA-Z0-9]+$/)) {
      error.lastName = "Last Name must be letters only";
    }
  }
  if (emailValue !== "") {
    //validating an email
    if (!emailValue.match(/^[a-zA-Z0-9.]+@[a-zA-Z0-9]+\.[a-zA-Z0-9]+$/)) {
      error.email = "Email must be a valid email";
    }
  }

  //if we have error add the error to the error message
  if (Object.keys(error).length > 0) {
    displayError();
  } else {
    //submit the form with a delay of 2 seconds
    //change the button innerText to submitting and add no-cursor class and disabled attribute to it
    buttonSubmit.value = "Submitting...";
    buttonSubmit.setAttribute("disabled", "disabled");

//set a delay of 2 seconds since we dont have an api endpoint to send the data to just mimic the process
    new Promise(function (resolve, reject) {
      setTimeout(function () {
        resolve(submitForm());
      }, 2000);
    });
  }
}

//display errors respectivey to the span html classes
function displayError() {
  //set all errors to their respectivey and also changing hidden 
error containers to be a block.
  if (error.firstName) {
    firstNameInput.classList.add("border-red-500");
    firstNameError.style.display = "block";
    firstNameError.innerHTML = error.firstName;
  }
  if (error.lastName) {
    lastNameInput.classList.add("border-red-500");
    lastNameError.style.display = "block";
    lastNameError.innerHTML = error.lastName;
  }
  if (error.email) {
    //loop over the classes and add other classes
    emailInput.classList.add("border-red-500");
    emailError.style.display = "block";
    emailError.innerHTML = error.email;
  }
}

//submitting the form
function submitForm() {
//TODO: Add an API ENDPOINT to send the data.

  //show the values for now but later we going to add some api intergration
  console.log(firstNameInput.value);
  console.log(lastNameInput.value);
  console.log(emailInput.value);
  //reset the login buttonSubmit

//after 2 seconds is over change the input type button innerText and remove the disabled attribute.
  buttonSubmit.value = "Login Now";
  buttonSubmit.removeAttribute("disabled");

  //reset the form and clear all fields
  form.reset();
}
```