Nixen85
Nixen85

Reputation: 1381

Check if all elements satisfy a condition with for-loop

I basically try to check if all input fields are valid by using the following code:

 addData (input){

   var isValid = false;    

   for (var i = 0, ii = input.length; i < ii; ++i) {          

      if ($('#' + input[i].id).hasClass('valid')) {
          isValid = true;              
      }
   }

   if (isValid) {
     //do stuff
   }
 }

In total the input.length is 3 and I want to check if all 3 input fields are valid. In my example, it just checks the last input element. In related posts, I couldn`t find a way to solve it with a for-loop. Can anybody help?

Thanks for all the helpful answers: Finally, I adjusted Máté Safranka's answer:

var isValid = input.toArray().every(element => $('#' + element.id).hasClass('valid'))

with .toArray() to convert jQuery object to an Array >> see here for more information. Defining true or false is not needed anylonger.

Upvotes: 0

Views: 3034

Answers (5)

M&#225;t&#233; Safranka
M&#225;t&#233; Safranka

Reputation: 4116

If input is an array, you can use .every():

var isValid = input.every(it => $('#' + it.id).hasClass('valid'));

If input isn't an array, you can convert it to an array with Array.from().

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

Note: As pointed out in the comments, this works in IE10 and later. This shouldn't be a problem most of the time (Windows 10 ships with IE11 and Edge, and theoretically every commercial end-user should have upgraded by now), but worth noting in case you have to support legacy platforms.

Upvotes: 3

T.J. Crowder
T.J. Crowder

Reputation: 1074148

As the others have said, you need to start off with isValid set to true and then as of the first invalid field, set it to false and break the loop.

But if input is really an array, I'd use input.every instead:

addData (input){
    if (input.every(function(element) { return $(element).hasClass('valid'); })) {
        // Do stuff
    }
}

Array#every calls the callback for the items in the array, returning true if the callback returns a truthy value for all of them, or returning false (and stopping immediately) if the callback ever returns a falsy value.

Or you could use jQuery's filter:

addData (input){
    if ($(input).filter(':not(.valid)').length === 0) {
        // Do stuff
    }
}

Array#every is more concise if you can use an ES2015+ arrow function:

addData (input){
    if (input.every(element => $(element).hasClass('valid'))) {
        // Do stuff
    }
}

Upvotes: 3

Federico klez Culloca
Federico klez Culloca

Reputation: 27119

anding true with isValid (as opposed to assigning true directly) will make it so the first false value will make the whole condition false. Just be sure to start with isValid as true before the loop.

isValid = true;

// inside the loop

isValid = isValid && true;

Upvotes: 0

fdomn-m
fdomn-m

Reputation: 28611

You never set isValid to false, so as long as at least one of the inputs is valid the result will be valid.

Better to swap the true/false and check for any invalid ones, eg:

addData (input){

 var isValid = true;    

 for (var i = 0, ii = input.length; i < ii; ++i) {          
   if (!$('#' + input[i].id).hasClass('valid')) {
      isValid = false;              
   }
 }

 if (isValid) {
  //do stuff
 }
}

Note: there are alternatives to using a loop, but this is to answer the explicit question of fixing the loop in OPs question.

Upvotes: 4

Oscar Paz
Oscar Paz

Reputation: 18292

You got it wrong. You're assuming invalid until an element is valid. And you should assume valid until one element is invalid:

addData (input){
   var isValid = true;    

   for (var i = 0, ii = input.length; i < ii; ++i) {          

      if (!($('#' + input[i].id).hasClass('valid'))) {
          isValid = false;              
      }
   }

   if (isValid) {
     //do stuff
   }
}

Upvotes: 3

Related Questions