0
votes

I'd like to add some checkbox info to an array before sending it off to a ajax post, but when it loops thru the checkboxes it seems to increment the number of items in the array but makes every entry in the array the same content. Here's my code.

var aData = [];
var item = [];
$(".providers_chk").each(function (index, element) {
    if ($(this).attr("checked")) {
        item[0] = element.value;
        item[1] = element.name;
        aData.push(item);
        console.log(aData);
    }
});

The array ends up looking like {"foo","bar"} for each entry, instead of {"foo","bar"} , {"foo1","bar1"} , {"foo2","bar2} etc

5
{"foo","bar"} is not a valid syntax. - Nina Scholz
You don't need if(), you can use the selector .providers_chk:checked. - Barmar

5 Answers

2
votes

In your code you use only one array for pushing, which gets for every loop new values. At the end, and while the reference to the same object is spreaded over the result array, you get the same values in all pushed arrays.

You could create arrays on the fly, which are not linked by reference together.

var aData = [];
$(".providers_chk").each(function (index, element) {
    if ($(this).attr("checked")) {
        aData.push([element.value, element.name]);
        console.log(aData);
    }
});
2
votes

Move var item = []; into the if:

if ($(this).attr("checked")) {
    var item = [];
    item[0] = element.value;
    item[1] = element.name;
    aData.push(item);
    console.log(aData);
}

Every iteration of the loop was modifying the same item array. Each item you pushed to aData was nothing but a reference to the same var item.

An shorter option is not to create a temporary variable at all:

if ($(this).attr("checked")) {
    aData.push([element.value, element.name]);
    console.log(aData);
}

Here's an example to illustrate the problem:

var item = ['foo'];   // Just like your `item`
var list = [];

while(list.length < 5)
  list.push(item);    // Add it to the list 5 times

console.log(JSON.stringify(list));

list[0][0] = 'bar';   // Edit the first `item` in the list's contents

console.log(JSON.stringify(list));

Each item in list is only a reference to the same var item.

2
votes

You are updating and pushing the same array reference inside the callback function. Instead use a local variable inside callback or generate array directly and push to the aData array.

Although you can refer the element using this inside the callback so there is no need to use callback arguments.

var aData = [];
$(".providers_chk").each(function () {
  if (this.checked) { // check the checked property
     aData.push([this.value, this.name]);
   }
});

$('.providers_chk').change(function() {
  var aData = [];
  $(".providers_chk").each(function() {
    if (this.checked) {
      aData.push([this.value, this.name]);
    }
  });
  console.log(aData);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="abc" class="providers_chk" value="1" />
<input type="checkbox" name="abc" class="providers_chk" value="2" />
<input type="checkbox" name="abc" class="providers_chk" value="3" />
<input type="checkbox" name="abc" class="providers_chk" value="4" />
<input type="checkbox" name="abc" class="providers_chk" value="5" />
<input type="checkbox" name="abc" class="providers_chk" value="6" />
<input type="checkbox" name="abc" class="providers_chk" value="7" />

if:checked
var aData = [];

$(".providers_chk:checked").each(function () {
   aData.push([this.value, this.name]);
});

$('.providers_chk').change(function() {
  var aData = [];

  $(".providers_chk:checked").each(function() {
    aData.push([this.value, this.name]);
  });

  console.log(aData);

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="abc" class="providers_chk" value="1" />
<input type="checkbox" name="abc" class="providers_chk" value="2" />
<input type="checkbox" name="abc" class="providers_chk" value="3" />
<input type="checkbox" name="abc" class="providers_chk" value="4" />
<input type="checkbox" name="abc" class="providers_chk" value="5" />
<input type="checkbox" name="abc" class="providers_chk" value="6" />
<input type="checkbox" name="abc" class="providers_chk" value="7" />

Or you can use jQuery.map method and :checked pseudo-class selector to make it simpler.

var aData = $.map($(".providers_chk:checked"), function(e) {
  return [e.value, e.name];
});

$('.providers_chk').change(function() {
  var aData = $.map($(".providers_chk:checked"), function(e) {
    return [e.value, e.name];
  });
  console.log(aData);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" name="abc" class="providers_chk" value="1" />
<input type="checkbox" name="abc" class="providers_chk" value="2" />
<input type="checkbox" name="abc" class="providers_chk" value="3" />
<input type="checkbox" name="abc" class="providers_chk" value="4" />
<input type="checkbox" name="abc" class="providers_chk" value="5" />
<input type="checkbox" name="abc" class="providers_chk" value="6" />
<input type="checkbox" name="abc" class="providers_chk" value="7" />
1
votes

Use the .map() function to return an array based on each matching element of a selector. Inside the callback you should return a new array, not reuse the same array as in your code.

var aData = $('.providers_chk:checked').map(function() {
    return [[this.value, this.name]];
}).get();

The nested array is necessary because jQuery automatically flattens a returned array, so you have to wrap it in an extra level so that you get a 2-dimensional array in the final result.

-1
votes
  var aData = [];
  $(".providers_chk").each(function (index, element) {
  if ($(this).attr("checked")) 
  {
    var item = new Object();
    item[0] = element.value;
    item[1] = element.name;
    aData.push(item);
    console.log(aData);
   }
  });

Hope it working for you :)