0

I create the very simple script below, in which I came with a question that I can't seem to find in the .each() documentation. As you see I would like to loop through a collection of jQuery objects and return either true or false (if one is false then the .each loop would break so the end result would be false)

For some reason the validation does not seem to work properly.

 $('.with-validation').on('submit', function (e) {
   if (isValid()) {
     console.log('validation succeded');
     return true;
   } else {
     console.log('validation failed');
     return false;
   }
 });
    
function isValid () {
  var $required = $('.required');
  var $emails = $('.email');
  var inputsValidation = function () {
    return $(this).val().length > 0;
  }
  $required.each(inputsValidation);
  return inputsValidation;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
    <form class="with-validation">
        <input name="lastname" class="required" type="text"></input>
        <input name="firstname" type="text"></input>
        <input name="phone" class="required" type="text"></input>
        <input name="email" class="required email" type="text"></input>
        <input name="confEmail" class="required email" type="text"></input>
        <button class="submit-btn" type="submit">OK</button>
    </form>
</body>

9
  • Could you provide more information? are there any errors? Commented Feb 21, 2017 at 9:58
  • What's the point of validateEmail() if it just returns true? Commented Feb 21, 2017 at 9:58
  • .each just iterates over a jquery collection. It does not return any value. If you want to use .each in your case you have to define external boolean flag and change it inside .each. Commented Feb 21, 2017 at 10:00
  • @HristiyanDodov none really, I'll remove it to not complicate things. (it's a reduced use-case) Commented Feb 21, 2017 at 10:01
  • @FabioAntunes you can run the snippet - the submit event shouldn't be triggered unless there's text in every "required" input field. Commented Feb 21, 2017 at 10:02

3 Answers 3

2

You can use Array.prototype.every if your function is looking for valid condition. Or use Array.prototype.some with a function checking for invalid condition. (Use a polyfill if you support < IE9)

Use .toArray to convert jQuery collection to an Array.

You are comparing the two functions itself inputsValidation && emailsValidation and not the result, also $each doesn't return result that way. Get the results to some variables and compare the results, not the function itself.

$('.with-validation').on('submit', function (e) {
   if (isValid()) {
     console.log('validation succeded');
     return true;
   } else {
     console.log('validation failed');
     return false;
   }
 });
    
function isValid () {
  var $required = $('.required').toArray();
  var $emails = $('.email').toArray();
  var emailsValidation = function (i) {
    return validateEmail(i.value);
  }
  var inputsValidation = function (i) {
    return i.value.length > 0;
  }

  var condition1 = $emails.every(emailsValidation);
  var condition2 = $required.every(inputsValidation);
  return condition1 && condition2;
}

function validateEmail(email) {
  return true;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
    <form class="with-validation">
        <input name="lastname" class="required" type="text"></input>
        <input name="firstname" type="text"></input>
        <input name="phone" class="required" type="text"></input>
        <input name="email" class="required email" type="text"></input>
        <input name="confEmail" class="required email" type="text"></input>
        <button class="submit-btn" type="submit">OK</button>
    </form>
</body>

Sign up to request clarification or add additional context in comments.

1 Comment

good one. Thank you for using native methods for this:) I guess we might as well dump jQuery all together and select the elements with vanilla JS..
1

jQuery unfortunately doesn't offer a method to filter for the first hit. ( .filter will find all that match). That's is why I made this small jQuery extension method, which will return the first element that doesn't match the filter.

$.fn.extend({
  firstMismatch: function(filter) {
    for(var element, i = 0; element = this[i]; i++) 
      if(!filter.call(element)) return element;
  }
});

Now to validate all input fields you simply have to call it like this. How does it work? $required.firstMismatch(inputsValidation) will return the first element that doesn't match the filter. So if it doesn't return any element, all match. The ! will inverse the returned value, so that no element returns true

  return !$required.firstMismatch(inputsValidation)  
      && !$emails.firstMismatch(emailsValidation)

This approach as has few benefits: you can do it in a single line, it checks only until one fails ( even prevents checking the mail at all if the required don't validate) and it gives you the option this to use.

.firstMismatch() can also be used for other things


solution

$('.with-validation').on('submit', function(e) {
  if (isValid()) {
    console.log('validation succeded');
    return true;
  } else {
    console.log('validation failed');
    return false;
  }
});

function isValid() {
  var $required = $('.required');
  var $emails = $('.email');
  
  var emailsValidation = function () {
    return validateEmail($(this).val());
  }
  
  var inputsValidation = function () {
    return $(this).val().length > 0;
  }

  return !$required.firstMismatch(inputsValidation) 
      && !$emails.firstMismatch(emailsValidation)

}

function validateEmail(email) {
  return true;
}

$.fn.extend({
  firstMismatch: function(filter) {
    for (var element, i = 0; element = this[i]; i++)
      if (!filter.call(element)) return element;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
    <form class="with-validation">
        <input name="lastname" class="required" type="text"/>
        <input name="firstname" type="text"/>
        <input name="phone" class="required" type="text"/>
        <input name="email" class="required email" type="text"/>
        <input name="confEmail" class="required email" type="text"/>
        <button class="submit-btn" type="submit">OK</button>
    </form>
</body>

4 Comments

vailedInput contains the length of all the valid input fields and $required.length contains the original length of all the arrays. Now you have to compare these two, if they match - all fields are valid. the 3 = just make sure the typ matches as well, but it's not strictly necessary. The same goes for the email.
.filter doesn't provide option to break the loop. It will run test callback for each element of collection even if test test fails on the first one.
@hindmost that's true. I'll think of a better solution
@GeorgeKatsanos indeed. I made an update, with what I believe, is the cleanest solution to your problem.
0

I changed a bit of your script, Hope this is what your "looking" for

I also change your "submit" trigger to allow you to run the example here. You should be able to use $('form.with-validation').on('submit',function(){})

$('.with-validation button').on('click', function() {
  if (isValid() == true) {
    console.log('validation succeded');
    return true;
  } else {
    console.log('validation failed');
    return false;
  }
});

function isValid() {
  var isvalid = true;
  $('.required').each(function() {
    if (isvalid) {
      if ($(this).hasClass("email")) {
        if (!validateEmail($(this).val())) {
          isvalid = false
        }

      } else {
        if ($(this).val().length == 0) {
          isvalid = false
        }
      }
    }
  })
  return isvalid
}


function validateEmail(emailAddress) {
  var pattern = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
  return pattern.test(emailAddress);
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <form class="with-validation">
    <input name="lastname" class="required" placeholder="lastname" type="text"></input>
    <input name="firstname" type="text" placeholder="firstname"></input>
    <input name="phone" class="required" type="text" placeholder="phone"></input>
    <input name="email" class="required email" type="text" placeholder="email"></input>
    <input name="confEmail" class="required email" type="text" placeholder="confEmail"></input>
    <button class="submit-btn" type="submit">OK</button>
  </form>
</body>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.