7

I know you are supposed to be able to break out of an each statement by returning, which is what I'm trying to do, but I must be doing something wrong and it seems so simple I can't find it.

I have code like this

function create() {
  var test = hasThing();
  if (test) {
    $('#myForm').submit();
  } else {
    alert('you suck!')
  }
}

function hasThing() {
  $('.selects').each(function() {
    if (this.value != "") {
      return true;
    }
  });
  return false;
}

I have set breakpoints on "return true;" and hit it but var test is always false because for some reason the .each() loop continues and the hasThing() function continues. I've tried switching things around so that I return false in the .each() just in case for some reason that mattered but it didn't change anything.

I don't get it. Seems counter to how the documentation says it should work.

2
  • 1
    To break .each you have to return false, and returning from inside the each loop does not return from the outer function. Commented Jul 21, 2014 at 17:40
  • 2
    Seems counter to how the documentation says it should work. - the documentation says "You can stop the loop from within the callback function by returning false". How is the behavior not inline with the docs? Commented Jul 21, 2014 at 17:44

2 Answers 2

15

Your return true; statement returns from the anonymous function given to each. The return false; line is always executed which explains why var test is always false.

Change your code to

function hasThing() {
  var hasThing = false;
  $('.selects').each(function() {
    if (this.value != "") {
      hasThing = true;
      return false; // breaks the $.each, but does not return from hasThing()
    }
  });
  return hasThing;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. That explains my mistake very well.
3

You could use Array.some() to check if any of the selects have a selected value

function hasThing() {
    return $('select').toArray().some(function(el) {
        return el.value != "";
    })
}

function create() {

    var test = hasThing();

    if (test) {
        alert('at least one select was changed');
        //$('#myForm').submit();
    } else {
        alert('you suck!');
    }
}

function hasThing() {
	return $('select').toArray().some(function(el) {
    	return el.value != "";
    })
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Select at least one option !</p>
<form id="myForm">
    <select class="selects">
        <option value="">blank</option>
        <option value="2">option1</option>
    </select>
    
    <select class="selects">
        <option value="">blank</option>
        <option value="2">option1</option>
    </select>
    
    <input type="button" onclick="create()" value="submit" />
    
</form>

12 Comments

Much easier to read (and, thus, maintain), though potentially much less efficient as the other suggestion supports "short-circuiting". Depends on how complex the this.value = logic actually is and how many elements are matched. Wish vanilla jQuery had a ".any()" function.
@JDB - It does, Array.some, but then the values would have to be mapped to an array, it's not really any more efficient, using a filter shouldn't be an issue here.
Doh. That would save you, on average, half the computation cycles (and time) and would not be particularly more difficult to implement.
@JDB - I don't see how, it would look something like -> jsfiddle.net/Lxg4k/1
... [].some.call($('.selects'), function(e) { return !!e.value; }) ?? (or with $.trim() of course)
|

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.