skip to Main Content

I am trying to create an input field with front-end validation. The idea is that when the user types in the password and unfocuses the input field, depending on the criteria that are not met the corresponding span will become red. As soon as they edit the input, if the criteria are met, they will return to the original color. How do I achieve this? I am attaching part of my code.

const inputFields = document.querySelectorAll('.common-input-class');

inputFields.forEach(function(inputField) {
  const errorMessage = inputField.parentElement.querySelector('.error-message');
  let hasError = false; //variable to track the input error state

  inputField.addEventListener('blur', function() {
    if (inputField.value.trim() === '') {
      inputField.style.border = '1.7px solid red';
      errorMessage.style.display = 'block';
      hasError = true;
    } else {
      inputField.style.border = '1.2px solid #ccc';
      errorMessage.style.display = 'none';
      hasError = false; // Reset the error state when unfocused
    }
  });

  inputField.addEventListener('input', function() {
    if (hasError) {
      inputField.style.border = '1.7px solid red';
      errorMessage.style.display = 'block';
    } else {
      inputField.style.border = '1.2px solid #ccc'; // Reset the border color on input
      errorMessage.style.display = 'none';
    }
  });
});

const passwordInput = document.getElementById('password');
const passwordErrorMessage = document.querySelector('.nenp .error-message');
const nenpDivs = document.querySelectorAll('.nenp');
let passwordHasError = false; //variable to track the password error state

passwordInput.addEventListener('blur', function() {
  if (passwordInput.value.trim() === '') {
    passwordInput.closest('.password').style.border = '1.7px solid red';
    passwordErrorMessage.style.display = 'block';
  } else {
    const span1 = nenpDivs[0].querySelector('span:nth-child(1)');
    const span2 = nenpDivs[0].querySelector('span:nth-child(2)');

    if (span1.style.color === 'red' || span2.style.color === 'red') {
      passwordInput.closest('.password').style.border = '1.7px solid red';
      passwordHasError = true;
    } else {
      passwordInput.closest('.password').style.border = '1.2px solid #ccc';
      passwordErrorMessage.style.display = 'none';
      passwordHasError = false; // Reset the error state when unfocused
    }
  }
});

passwordInput.addEventListener('input', function() {
  const inputValue = passwordInput.value.trim();

  nenpDivs.forEach(function(nenpDiv) {
    const span1 = nenpDiv.querySelector('span:nth-child(1)');
    const span2 = nenpDiv.querySelector('span:nth-child(2)');

    if (inputValue.length < 8) {
      span1.style.color = 'red'; // Change to red when the criteria are not met
      passwordHasError = true;
    } else {
      span1.style.color = ''; // Reset to the original color when the criteria are met
    }

    if (/[A-Z]/.test(inputValue) && /d/.test(inputValue)) {
      span2.style.color = ''; // Reset to the original color when the criteria are met
      passwordHasError = false; // Reset the error state when the criteria are met
    } else {
      span2.style.color = 'red'; // Change to red when the criteria are not met
      passwordHasError = true;
    }
  });
});

// Add a blur event listener to passwordInput to set passwordHasError when it loses focus
passwordInput.addEventListener('blur', function() {
  if (passwordHasError) {
    passwordInput.closest('.password').style.border = '1.7px solid red';
  } else {
    passwordInput.closest('.password').style.border = '1.2px solid #ccc';
  }
});
.error-message {
  position: relative;
  color: rgb(251, 70, 34);
  margin-top: -27px;
  margin-left: 14px;
  display: none;
}
<div class="data-form nenp">
  <label for="number">Password </label>
  <div class="password">

    <input type="password" id="password" autocomplete="off" required>
    <div class="visibility">
      <a>eye</a>
    </div>
  </div>

  <span class="error-message">required</span>
  <div style="margin-top: -10px; display: grid;">
    <span>Minimum 6 characters</span>
    <span>Must include an Uppercase and number </span>
  </div>
</div>

2

Answers


  1. You can get it that way, you just have to adjust it to your criteria

    const passwordInput = document.getElementById('passwordInput');
    const lengthValidation = document.getElementById('lengthValidation');
    const uppercaseValidation = document.getElementById('uppercaseValidation');
    const numberValidation = document.getElementById('numberValidation');
    
    function validatePassword() {
      const password = passwordInput.value;
    
      // Check criteria and change colors accordingly
      if (password.length >= 8) {
        lengthValidation.classList.remove('error'); // Criteria met
      } else {
        lengthValidation.classList.add('error'); // Criteria not met
      }
    
      if (/[A-Z]/.test(password)) {
        uppercaseValidation.classList.remove('error'); // Criteria met
      } else {
        uppercaseValidation.classList.add('error'); // Criteria not met
      }
    
      if (/d/.test(password)) {
        numberValidation.classList.remove('error'); // Criteria met
      } else {
        numberValidation.classList.add('error'); // Criteria not met
      }
    }
    
    function checkWhileWriting() {
      const password = passwordInput.value;
    
      // Check criteria and change colors accordingly
      if (password.length >= 8) {
        lengthValidation.classList.remove('error'); // Criteria met
      }
    
      if (/[A-Z]/.test(password)) {
        uppercaseValidation.classList.remove('error'); // Criteria met
      }
    
      if (/d/.test(password)) {
        numberValidation.classList.remove('error'); // Criteria met
      }
    }
    passwordInput.addEventListener('blur', validatePassword);
    
    // Add an input event listener to check criteria while typing
    passwordInput.addEventListener('input', checkWhileWriting);
    .error {
      color: red;
      /* Color when criteria are not met */
    }
    <label for="passwordInput">Password:</label>
    <input type="password" id="passwordInput">
    <br>
    <span id="lengthValidation">Password must be at least 8 characters long</span>
    <br>
    <span id="uppercaseValidation">Password must contain at least one uppercase letter</span>
    <br>
    <span id="numberValidation">Password must contain at least one number</span>
    Login or Signup to reply.
  2. Hello I saw your code and it’s a bit messy to understand at first, but the idea was there, Keep it up!

    I got inspired by how it worked and created this, where the code is less repetitive, more readable and easy to change.

    Before you see the code be aware that: This code use JS that add classes to items that are being stylized with CSS. To change any of the looks depending on what you want, just change the CSS. Basically JS is linked with CSS.

    Hope this helps! 🙂

    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Password Verify</title>
    
        <link rel="stylesheet" href="Style.css" />
      </head>
      <body>
        <div id="WrapDiv">
          <label for="password">Password</label>
          <div class="password">
            <input type="password" id="password" autocomplete="off" required />
            <div class="visibility"><a>eye</a></div>
          </div>
    
          <span class="ErrorMessage">Required</span>
          <div class="RequiredForPassword">
            <span>Minimum 6 characters</span>
            <span>Must include an Uppercase and number</span>
          </div>
        </div>
    
        <script src="Code.js"></script>
      </body>
    </html>
    

    Style.css

    /* password input */
    .password {
      display: grid;
      width: max-content;
      max-width: 100%;
      grid-template-columns: auto auto;
      gap: 0.5em;
    }
    
    /* visibility button 'eye' */
    .visibility {
      width: fit-content;
      display: block;
      cursor: pointer;
    }
    
    /* RequiredForPassword attributes */
    .RequiredForPassword {
      display: grid;
      grid-auto-rows: 1fr;
    }
    
    /* Error */
    .Error {
      border: 1.7px solid red;
    }
    
    /* ErrorMessage ('required') */
    .ErrorMessage {
      display: none;
    }
    
    /* 
      if(.password child that has a class of 'Empty'){
        get the sibling element that have a class of 'ErrorMessage'
      }
    */
    .password:has(> .Empty) + .ErrorMessage {
      display: block;
      color: red;
    }
    
    /* 
      if(.password child that has a class of 'Error'){
        get the sibling element that have a class of 'RequiredForPassword'
      }
    */
    .password:has(> .Error) + .RequiredForPassword {
      color: rebeccapurple !important;
    }
    
    /* RequiredForPasswordError */
    .RequiredForPasswordError {
      color: red;
    }
    

    Code.js

    var Password = document.getElementById("password"); // Get password input
    var WrapDiv = document.getElementById("WrapDiv"); // Get password whole wrap div
    var HasError = false; // Input has error
    
    var WaitToValidate = ""; // Setup for timer
    var OldLetter = null; // See the old letter typed
    
    // Get the 1° RequiredForPassword span
    const span1 = WrapDiv.querySelector(".RequiredForPassword :nth-child(1)");
    
    // Get the 2° RequiredForPassword span
    const span2 = WrapDiv.querySelector(".RequiredForPassword :nth-child(2)");
    
    // When input is unfocused
    Password.addEventListener("blur", () => {
      // Check if password value it's empty
      if (Password.value.trim() === "") {
        // If it is style the input with css by class
        Password.classList.add("Error");
    
        // Add the class when input is empty
        Password.classList.add("Empty");
        HasError = true;
      } else {
        // If it is not empty, remove the style of input with css by class
        Password.classList.remove("Empty");
    
        // Remove the class when input is not empty
        Password.classList.remove("Error");
        HasError = true;
      }
    });
    
    Password.addEventListener("input", (e) => {
      clearTimeout(WaitToValidate); // Clear timeout
    
      // If the user is deleting and the value of the input is empty
      if (e.inputType == "deleteContentBackward" && Password.value.trim() == "") {
        // Validade, to show 'required'
        Validate();
        // If the user is typing something and the old value of the input is was empty
      } else if (e.inputType == "insertText" && OldLetter == "") {
        // Validade, to remove the 'required'
        Validate();
    
        span1.classList.remove("RequiredForPasswordError");
        span2.classList.remove("RequiredForPasswordError");
      } else {
        /*
          If the user types something, wait a second (1000 miliseconds) until validating
    
          The timeout will clear if the user types something before the 1 second timeout,
          as seen in the 'clearTimeout(WaitToValidate);'
        */
    
        WaitToValidate = setTimeout(() => {
          Validate();
        }, 1000);
    
        // To change the time after the user finished writing, change the number. It's in miliseconds (ms)
        // 1 second = 1000 miliseconds
        // 0.5 seconds = 500 ms
      }
    
      OldLetter = Password.value.trim();
    });
    
    function Validate() {
      const PasswordValue = Password.value.trim(); // Get Password value and save in a variable
    
      // Check password value if it's empty
      if (PasswordValue === "") {
        // If it is add the class when input is empty
        Password.classList.add("Empty");
        span1.classList.add("RequiredForPasswordError");
        span2.classList.add("RequiredForPasswordError");
        HasError = true;
      } else {
        // If it is not empty, remove the class when input is not empty
        Password.classList.remove("Empty");
    
        HasError = false;
    
        // To optimize the code, remove unecessary checks when the password is empty
    
        // If the input value has a lenght less than 6
        if (PasswordValue.length < 6) {
          // Make the 1° required item be stylized with a class
          span1.classList.add("RequiredForPasswordError");
          HasError = true;
        } else {
          // Else if the input value has a lenght more or equal than 6
          // Remove the 1° required item class
          span1.classList.remove("RequiredForPasswordError");
        }
    
        // If the input has Uppercase letter AND number
        if (/[A-Z]/g.test(PasswordValue) && /d/g.test(PasswordValue)) {
          // Remove the 2° required item class
          span2.classList.remove("RequiredForPasswordError");
          HasError = false;
        } else {
          // Else if the input has Uppercase letter OR number OR etheir
          // Make the 2° required item be stylized with a class
          span2.classList.add("RequiredForPasswordError");
          HasError = true;
        }
      }
    
      // If there is error
      if (HasError) {
        // Make the Password input be stylized with a class
        Password.classList.add("Error");
      } else {
        // Remove the Password input class
        Password.classList.remove("Error");
      }
    }
    

    [ Edited ]
    How it works:

    In js there is a functionality where you can delay the execution of things, you can do it by using the timeout funcion by vanilla JS.

    setTimeout(function, timeInMS);

    setTimeout(() => {
        // Execute after 1000ms
    }, 1000);
    

    You can use it as this too!

    setTimeout(myfunc, 1000);
    
    function myfunc(){
      alert('hello!');
    }
    

    To clear a time out, you have to save it in a variable, otherwise it will give an error

    First save the time out in a variable

    let MyTimeOut = setTimeout(() => {
        // Execute after 2 seconds
    }, 2000);
    

    Secondly when you want to stop it, just type

    clearTimeout(MyTimeOut);
    

    clearTimeout(TIMEOUTNAME);

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search