user3574603
user3574603

Reputation: 3628

Why isn't my map() call returning the expected result?

I have a form with three checkboxes:

<form id="checklist-form" action="">
  <h1>this</h1>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item0" required="">
    <label class="form-check-label" for="check-item0">
     One
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item1" required="">
    <label class="form-check-label" for="check-item1">
      Two
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item2" required="">
    <label class="form-check-label" for="check-item2">
      Three
    </label>
  </div>
</form>

I want to get the value of each of the checkboxes so that I can store them in a cookie.

One my page, the first checkbox is checked. The other two are unchecked. I can use jQuery to see that the first box is checked:

$('#checklist-form input[type="checkbox"]').first().is(':checked')
// > true

Likewise, I can see the second element is not checked:

$($('#checklist-form input[type="checkbox"]')[1]).is(':checked')
// > false

Instead of querying each checkbox in turn, I want to use map to return an array. However, I'm not having much luck:

$('#checklist-form input[type="checkbox"]').map(function(el){ return $(el).is(':checked') }).toArray()
// > (3) [false, false, false]

I expect [true, false, false]. So what am I doing wrong? And is converting the checkbox states to an array entirely the correct approach if I want to store the form's state to a cookie?

Upvotes: 0

Views: 24

Answers (1)

Rory McCrossan
Rory McCrossan

Reputation: 337743

The issue is because you're using the first argument of map(), which is the index of the element in the collection, instead of the second argument, which is the reference to the element itself:

var arr = $('#checklist-form input[type="checkbox"]').map(function(i, el) {
  return $(el).is(':checked');
}).toArray();
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="checklist-form" action="">
  <h1>this</h1>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item0" required="" checked="true">
    <label class="form-check-label" for="check-item0">
     One
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item1" required="">
    <label class="form-check-label" for="check-item1">
      Two
    </label>
  </div>
  <div class="form-check">
    <input class="form-check-input" type="checkbox" value="" id="check-item2" required="">
    <label class="form-check-label" for="check-item2">
      Three
    </label>
  </div>
</form>

Also note that you can get the checked property from the element directly and use get() instead of toArray() to improve the performance of the logic slightly:

var arr = $('#checklist-form input[type="checkbox"]').map(function(i, el) {
  return el.checked;
}).get();

Or even, as @charlietfl pointed out, you could remove the reliance on the arguments passed to the handler function and use the this keyword within the handler function, as it's called with the scope of the element provided:

var arr = $('#checklist-form input[type="checkbox"]').map(function() {
  return this.checked;
}).get();

Upvotes: 2

Related Questions