jQuery - Input validation iterate error for multiple instances

Viewed 84

The error validation works if there is only one instance of .item however when I duplicate the item and try to validate the input, the inputError function seems to run on every instance instead of just the one being validated.

How do I run the validate function on the only the inputs inside of each .item?

$(document).ready(function() {
  var $items = $(".item");
  $items.each(function() {
    var $input = $(this).find(".input");
    var inputCheck = function() {
      var errorList = $("ul.errorMessages", $items);
      var inputError = function() {
        errorList.empty();
        $items.find(":invalid").each(function(index, node) {
          var label = $(node).attr("name");
          var message = node.validationMessage || "Invalid value.";
          errorList
            .show()
            .append(
              "<li><span>" + label + ": " + "</span>" + message + "</li>"
            );
        });
      };
      $("input[type=submit], button", $items).on("click", inputError);
    };
    inputCheck();
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form">
  <div class="item">
    <div class="success"></div>
    <ul class="errorMessages"></ul>
    <label>
      <input required class="input" name="first" type="text" placeholder="first">
    </label>
    <label>
      <input required class="input" name="second" type="text" placeholder="second">
    </label>
    <button type="submit">Create</button>
  </div>
  <div class="item">
    <div class="success"></div>
    <ul class="errorMessages"></ul>
    <label>
      <input required class="input" name="first_2" type="text" placeholder="first">
    </label>
    <label>
      <input required class="input" name="second_2" type="text" placeholder="second">
    </label>
    <button type="submit">Create</button>
  </div>
</div>

2 Answers

this is tricky but you can store current item being iterated in a variable such as $this and then manipulate it

$(document).ready(function() {
  var $items = $(".item");
  $items.each(function() {
    var $this = $(this);
    var $input = $this.find(".input");
    var inputCheck = function() {
      var errorList = $("ul.errorMessages", $this);
      var inputError = function() {
        errorList.empty();
        $this.find(":invalid").each(function(index, node) {
          var label = $(node).attr("name");
          var message = node.validationMessage || "Invalid value.";
          errorList
            .show()
            .append(
              "<li><span>" + label + ": " + "</span>" + message + "</li>"
            );
        });
      };
      $("input[type=submit], button", $this).on("click", inputError);
    };
    inputCheck();
  });
});

here is fiddle: https://jsfiddle.net/rjpyqms9/

I would put simplify the code and create a function with a simpler set of code in it and call that. You will also want the submit event in case someone triggers it - like from a keyboard. Note I attached the event handler to the .item to simplify the code;

NOTE: I assume some sort of a validate plugin etc. exists to put the :invalid in there. EDIT: thought about it and made it simpler.

$(function() {
  function inputError(event) {
    // the item
    let item = $(event.delegateTarget);
    let invalids = item.find(':invalid');
    if (invalids) {
      let errorList = item.find(".errorMessages")
      errorList.empty();
      invalids 
        .each(function(index, node) {
          let label = $(node).attr("name");
          let message = node.validationMessage || "Invalid value.";
          errorList
            .append("<li><span>" + label + ": " + "</span>" + message + "</li>")
            .show();
        });
    }
  }
  $('.form').find('.item').on('click submit', "button[type=submit]", inputError);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form">
  <div class="item">
    <div class="success"></div>
    <ul class="errorMessages"></ul>
    <label>
      <input required class="input" name="first" type="text" placeholder="first">
    </label>
    <label>
      <input required class="input" name="second" type="text" placeholder="second">
    </label>
    <button type="submit">Create</button>
  </div>
  <div class="item">
    <div class="success"></div>
    <ul class="errorMessages"></ul>
    <label>
      <input required class="input" name="first_2" type="text" placeholder="first">
    </label>
    <label>
      <input required class="input" name="second_2" type="text" placeholder="second">
    </label>
    <button type="submit">Create</button>
  </div>
</div>

Related