form validation message (dynamic)

Is there a way to dynamically tell which .input has yet to be entered? In the code below you can see that if I enter out of order, the #message only counts how many inputs have been populated and displays the message listed in order under numValid == 1, 2, 3, etc.

Can the code be changed to dynamically display a message for the .inputs that have not been populated?

*****Example: if I type in the Last Name and Student ID field, the message will either tell me to enter in the First Name or City field, etc. until they are all populated and the last validation (success message) is displayed*****

$("#form input").keyup(function() {
  var numValid = 0;
  $("#form input[required]").each(function() {
    if (this.validity.valid) {
      numValid++;
    }
  });

  var progress = $("#progress"),
    progressMessage = $("#message");

  if (numValid == 1) {
    progress.attr("value", "25");
    progressMessage.text("Please Enter the First Name.");
  }
  if (numValid == 2) {
    progress.attr("value", "50");
    progressMessage.text("Please Enter the Last Name.");
  }
  if (numValid == 3) {
    progress.attr("value", "75");
    progressMessage.text("Please Enter a City.");
  }
  if (numValid == 4) {
    progress.attr("value", "100");
    progressMessage.text("You're done, post!");
  }
});
#mainformdiv {
  margin-left: auto;
  margin-right: auto;
  width: 500px;
  border: 1px solid;
  border-radius: 10px;
}

#form {
  padding: 20px;
}

#progress {
  width: 460px;
  height: 25px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mainformdiv">
  <form id="form">
    <div id="progressdiv">
      <progress max="100" value="0" id="progress"></progress>
      <div id="message">Progress Message...</div>
    </div>
    <div class="input">
      <label for="userid">Student ID</label><br>
      <input id="userid" required="required" type="text">
    </div>
    <div class="input">
      <label for="firstname">First Name</label><br>
      <input id="firstname" required="required" type="text">
    </div>
    <div class="input">
      <label for="lastname">Last Name</label><br>
      <input id="lastname" required="required" type="text">
    </div>
    <div class="input">
      <label for="city">City</label><br>
      <input id="city" required="required" type="text"></br>
    </div>
  </form>
</div>

1 answer

  • answered 2018-04-17 05:03 CertainPerformance

    Easy to accomplish, just iterate over all of the required fields, and join their ids into a string. If you want to display a nicer looking name, then just map the IDs to an object first.

    $("#form input").keyup(function() {
      var numValid = 0;
      $("#form input[required]").each(function() {
        if (this.validity.valid) {
          numValid++;
        }
      });
      
      var progress = $("#progress"),
        progressMessage = $("#message");
    
    const invalidInputs = Array.from(document.querySelectorAll('#form input[required]'))
      .filter(input => !input.validity.valid)
      .map(input => input.id);
      
      progress.attr("value", numValid * 25);
      if (numValid == 4) {
        progressMessage.text("You're done, post!");
      } else {
        progressMessage.text('Please fill out the following fields: ' + invalidInputs.join(', '));
      }
    });
    #mainformdiv {
      margin-left: auto;
      margin-right: auto;
      width: 500px;
      border: 1px solid;
      border-radius: 10px;
    }
    
    #form {
      padding: 20px;
    }
    
    #progress {
      width: 460px;
      height: 25px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="mainformdiv">
      <form id="form">
        <div id="progressdiv">
          <progress max="100" value="0" id="progress"></progress>
          <div id="message">Progress Message...</div>
        </div>
        <div class="input">
          <label for="userid">Student ID</label><br>
          <input id="userid" required="required" type="text">
        </div>
        <div class="input">
          <label for="firstname">First Name</label><br>
          <input id="firstname" required="required" type="text">
        </div>
        <div class="input">
          <label for="lastname">Last Name</label><br>
          <input id="lastname" required="required" type="text">
        </div>
        <div class="input">
          <label for="city">City</label><br>
          <input id="city" required="required" type="text"></br>
        </div>
      </form>
    </div>