skip to Main Content

I am trying to add my error message and icon for all inputs that are invalid, however, it only works for the first input. What am i doing wrong? This is not my full solution just a piece of code that is not working, I intend to solve the rest on my own.

I tried using input.value to but that did not work either.

const input = document.querySelectorAll("input");

input.forEach((input) => {
  input.addEventListener("invalid", getErrorMsg);

  input.addEventListener("focus", removeErrorMsg);


})

function getErrorMsg(e) {
  const errorIcon = document.querySelector(".error-icon");
  const errorTxt = document.querySelector(".error-txt");
  errorIcon.classList.add("active");
  errorTxt.classList.add("active");

};

function removeErrorMsg(e) {
  const errorIcon = document.querySelector(".error-icon");
  const errorTxt = document.querySelector(".error-txt");
  errorIcon.classList.remove("active");
  errorTxt.classList.remove("active");
}
.inputDiv {
  position: relative;
  border: 1px solid transparent;
}

.error-icon {
  display: none;
  position: absolute;
  top: 18px;
  right: 30px;
}

.error-txt {
  display: none;
  color: var(--CLR-RED);
  font-style: italic;
  font-size: 0.8em;
  font-weight: var(--FW-BOLD);
  position: absolute;
  bottom: -10px;
  right: 0;
}

.error-icon.active,
.error-txt.active {
  display: block;
}
<form class="formContainer">
  <div class="inputDiv">
    <input class="input" type="text" id="firstName" name="firstName" placeholder="First Name" required>
    <img class="error-icon" src="images/icon-error.svg" alt="">
    <p class="error-txt">First Name cannot be empty</p>
  </div>

  <div class="inputDiv">
    <input class="input" type="text" id="lastName" name="lastName" placeholder="Last Name" required>
    <img class="error-icon" src="images/icon-error.svg" alt="">
    <p class="error-txt">Last Name cannot be empty</p>
  </div>

  <div class="inputDiv">
    <input class="input" type="email" id="email" name="email" placeholder="Email Address" required>
    <img class="error-icon" src="images/icon-error.svg" alt="">
    <p class="error-txt">Looks like this is not an email</p>
  </div>

  <div class="inputDiv">
    <input class="input" type="password" id="password" name="password" placeholder="Password" required>
    <img class="error-icon" src="images/icon-error.svg" alt="">
    <p class="error-txt">Password cannot be empty</p>
  </div>

  <button type="submit" class="freeTrialBtn">
  Claim your free trial 
</button>
</form>

2

Answers


  1. If I understood the assignment correctly, you are fighting with the default browser validation behavior. It will display an error for the first incorrect input only (tooltip and icon). Usually, you would want to add novalidate property on <form> and come up with your own validation, something like this:

    (Also, your query selector selects first input only, you have to select parent selector and grab an array of inputs instead).

    // Wait for the DOM to be fully loaded
    document.addEventListener("DOMContentLoaded", function() {
    
      const form = document.querySelector(".formContainer");
      const inputs = document.querySelectorAll(".input"); // Select inputs with class 'input'
    
      // Prevent the form's default submission behavior and validate inputs manually
      form.addEventListener("submit", function(e) {
        e.preventDefault(); // Stop the form from submitting
    
        let formIsValid = true;
    
        inputs.forEach(function(input) {
          if (!input.checkValidity()) {
            formIsValid = false;
            showErrorMsg(input);
          } else {
            removeErrorMsg(input);
          }
        });
    
        if (formIsValid) {
          // All inputs are valid, proceed with form submission or other logic
          console.log("Form submitted successfully!");
          // You can submit the form here if needed
          // form.submit();
        }
      });
    
      // Add event listeners to inputs to validate on input and remove errors when corrected
      inputs.forEach(function(input) {
        input.addEventListener("input", function() {
          if (input.checkValidity()) {
            removeErrorMsg(input);
          } else {
            showErrorMsg(input);
          }
        });
      });
    
      function showErrorMsg(input) {
        const parentDiv = input.closest(".inputDiv");
        const errorIcon = parentDiv.querySelector(".error-icon");
        const errorTxt = parentDiv.querySelector(".error-txt");
    
        input.classList.add('invalid'); // Optional: Add a class to style invalid inputs
        errorIcon.classList.add("active");
        errorTxt.classList.add("active");
      }
    
      function removeErrorMsg(input) {
        const parentDiv = input.closest(".inputDiv");
        const errorIcon = parentDiv.querySelector(".error-icon");
        const errorTxt = parentDiv.querySelector(".error-txt");
    
        input.classList.remove('invalid'); // Optional: Remove invalid class when input is valid
        errorIcon.classList.remove("active");
        errorTxt.classList.remove("active");
      }
    
    });
    /* Base styles for the form */
    .formContainer {
      max-width: 400px;
      margin: 0 auto;
      font-family: Arial, sans-serif;
    }
    
    .inputDiv {
      position: relative;
      margin-bottom: 40px; /* Adjust spacing between inputs */
    }
    
    .input {
      width: 100%;
      padding: 10px;
      font-size: 16px;
      box-sizing: border-box;
    }
    
    .input.invalid {
      border-color: red; /* Highlight invalid inputs */
    }
    
    ::placeholder {
      color: #ccc;
    }
    
    /* Error icon styling */
    .error-icon {
      display: none;
      position: absolute;
      top: 20px;
      right: 10px;
      transform: translateY(-50%);
      width: 20px;
      height: 20px;
    }
    
    .error-icon.active {
      display: block;
    }
    
    /* Error text styling */
    .error-txt {
      display: none;
      color: red; /* Or use var(--CLR-RED) if defined */
      font-style: italic;
      font-size: 0.8em;
      font-weight: bold; /* Or use var(--FW-BOLD) if defined */
      bottom: -20px;
      left: 0;
    }
    
    .error-txt.active {
      display: block;
    
    }
    
    /* Button styling */
    .freeTrialBtn {
      padding: 12px 20px;
      font-size: 16px;
      width: 100%;
      cursor: pointer;
      background-color: #28a745; /* Green background */
      color: white;
      border: none;
      border-radius: 4px;
    }
    
    .freeTrialBtn:hover {
      background-color: #218838; /* Darker green on hover */
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Form Validation Example</title>
      <!-- Link to your CSS file -->
      <link rel="stylesheet" href="styles.css">
    </head>
    <body>
    
      <form class="formContainer" novalidate>
        <div class="inputDiv">
          <input class="input" type="text" id="firstName" name="firstName" placeholder="First Name" required>
          <img class="error-icon" src="https://unicons.iconscout.com/release/v4.0.0/svg/solid/exclamation-circle.svg" alt="Error Icon">
          <p class="error-txt">First Name cannot be empty</p>
        </div>
    
        <div class="inputDiv">
          <input class="input" type="text" id="lastName" name="lastName" placeholder="Last Name" required>
          <img class="error-icon" src="https://unicons.iconscout.com/release/v4.0.0/svg/solid/exclamation-circle.svg" alt="Error Icon">
          <p class="error-txt">Last Name cannot be empty</p>
        </div>
    
        <div class="inputDiv">
          <input class="input" type="email" id="email" name="email" placeholder="Email Address" required>
          <img class="error-icon" src="https://unicons.iconscout.com/release/v4.0.0/svg/solid/exclamation-circle.svg" alt="Error Icon">
          <p class="error-txt">Looks like this is not an email</p>
        </div>
    
        <div class="inputDiv">
          <input class="input" type="password" id="password" name="password" placeholder="Password" required>
          <img class="error-icon" src="https://unicons.iconscout.com/release/v4.0.0/svg/solid/exclamation-circle.svg" alt="Error Icon">
          <p class="error-txt">Password cannot be empty</p>
        </div>
    
        <button type="submit" class="freeTrialBtn">
          Claim your free trial 
        </button>
      </form>
    
      <!-- Include your JavaScript file -->
      <script src="script.js"></script>
    </body>
    </html>
    Login or Signup to reply.
  2. For both callback functions, you can get the current form field using e.target. You can write less code if you just set a class name on the form field (here, invalid). And then you can use the Subsequent-sibling combinator to change the style of the image and the error text.

    const form01 = document.forms.form01;
    
    form01.addEventListener("invalid", getErrorMsg, true);
    form01.addEventListener("input", removeErrorMsg);
    
    function getErrorMsg(e) {
      e.preventDefault();
      e.target.classList.add('invalid');
    };
    
    function removeErrorMsg(e) {
      if (e.target.validity.valid) {
        e.target.classList.remove('invalid');
      }
    }
    .inputDiv {
      position: relative;
      border: 1px solid transparent;
    }
    
    .error-icon {
      display: none;
      position: absolute;
      top: 18px;
      right: 30px;
    }
    
    .error-txt {
      display: none;
      color: var(--CLR-RED);
      font-style: italic;
      font-size: 0.8em;
      font-weight: var(--FW-BOLD);
      position: absolute;
      bottom: -10px;
      right: 0;
    }
    
    input.invalid~.error-icon,
    input.invalid~.error-txt {
      display: block;
    }
    <form name="form01" class="formContainer">
      <div class="inputDiv">
        <input class="input" type="text" id="firstName" name="firstName" placeholder="First Name" required>
        <img class="error-icon" src="images/icon-error.svg" alt="">
        <p class="error-txt">First Name cannot be empty</p>
      </div>
    
      <div class="inputDiv">
        <input class="input" type="text" id="lastName" name="lastName" placeholder="Last Name" required>
        <img class="error-icon" src="images/icon-error.svg" alt="">
        <p class="error-txt">Last Name cannot be empty</p>
      </div>
    
      <div class="inputDiv">
        <input class="input" type="email" id="email" name="email" placeholder="Email Address" required>
        <img class="error-icon" src="images/icon-error.svg" alt="">
        <p class="error-txt">Looks like this is not an email</p>
      </div>
    
      <div class="inputDiv">
        <input class="input" type="password" id="password" name="password" placeholder="Password" required>
        <img class="error-icon" src="images/icon-error.svg" alt="">
        <p class="error-txt">Password cannot be empty</p>
      </div>
    
      <button type="submit" class="freeTrialBtn">
      Claim your free trial 
    </button>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search