Micah Wierenga Micah Wierenga - 12 days ago 7
jQuery Question

Values from unchecked checkboxes returning as "undefined"

I'm sure this has been addressed elsewhere, but I've read 20+ stackoverflow entries trying to find an answer, but all the ones I've read don't address this exactly and when I try to adopt proposed solutions, they just don't work. I'm having issues with unchecked checkboxes in Mad Libs returning a value of "undefined," so that the code below returns the following (if, for example, #check3 is checked and the other two are not):

In the end, their success can be contributed entirely to their undefined, undefined, dedicated [#noun-2 value, which is working just fine].

var $end = " In the end, their success can be contributed entirely to their " + $('#check1:checked').val() + ", " + $('#check2:checked').val() + ", " + $('#check3:checked').val() + " " + $('#noun-2').val() + ".";


Any idea of how I can return the values of only checked checkboxes? Do I need to write an if/else to make this happen?

Sorry about that, I forgot to post html. Here it is:

<div class="checkboxes">
<div class="check">
<input id="check1" type="checkbox" name="adjective-2" value="powerful">
<label for="check1">powerful</label>
</div>
<div class="check">
<input id="check2" type="checkbox" name="adjective-2" value="honed">
<label for="check2">honed</label>
</div>
<div class="check">
<input id="check3" type="checkbox" name="adjective-2" value="dedicated">
<label for="check3">dedicated</label>
</div>
</div>


Thank you.

Answer

Working Fiddle

To get this you can loop through the checked checkboxes, convert the values to an array, and then loop through the array to create a readable list.

Gathering Values

To gather the values, loop through each checked checkbox and add them to an array.

function convertToArray() {
  var array = [];
  $('input[type=checkbox]:checked').each(function() {
    array.push($(this).val());
  });
  return array;
}

Making the values readable

You can then reduce the array to a readable human list by calling reduce with the following function:

function readableList(prev, curr, i, a) {
  let term = curr.toLowerCase();
  let grammer = (a.length === i + 1 && a.length > 1) ? ', and ' : (i > 0 ? ', ' : '');
  return `${prev}${grammer}${term}`;
}

Putting it together

To tie the pieces together you can call an update function like this

function onUpdate() {
  var array = convertToArray();
  var list = array.reduce(readableList, '');

  var end = " In the end, their success can be contributed entirely to their " + list + " " + $('#noun-2').val() + ".";
  $('#result').text(end);
}

Full code

$('#updateButton').click(function(){
	onUpdate();
});

function onUpdate() {
  var array = convertToArray();
  var list = array.reduce(readableList, '');
  
  var end = " In the end, their success can be contributed entirely to their " + list + " " + $('#noun-2').val() + ".";
  $('#result').text(end);
}

function convertToArray() {
  var array = [];
  $('input[type=checkbox]:checked').each(function() {
  	array.push($(this).val());
  });
  return array;
}

function readableList(prev, curr, i, a) {
  let term = curr.toLowerCase();
  let grammer = (a.length === i + 1 && a.length > 1) ? ', and ' : (i > 0 ? ', ' : '');
  return `${prev}${grammer}${term}`;
}
label {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="checkboxes">
    <div class="check">
        <input id="check1" type="checkbox" name="adjective-2" value="powerful"> 
        <label for="check1">powerful</label>
    </div>
    <div class="check">
        <input id="check2" type="checkbox" name="adjective-2" value="honed">
        <label for="check2">honed</label> 
    </div>
    <div class="check">
        <input id="check3" type="checkbox" name="adjective-2" value="dedicated"> 
        <label for="check3">dedicated</label>
    </div>
</div>
<input type="text" value="house" id="noun-2">

<button id="updateButton">Update</button>

<h1>Result:</h1>
<div id="result"></div>