0

I have a case where radio button groups are generated dynamically in a form.

Requirements:

  • The number of buttons per group could be one or many.
  • There is a function which checks whether a radio button selection has been made and alerts an error if no selection is made.

When there is only one radio button the check fails and alerts an error, even when the button is selected. When I log (or in this case alert) the form element I get a different object type for a single group or a multiple group: HTMLInputElement vs RadioNodeList. Since the check function checkkRb() iterates through a list and HTMLInputElement returns a length of undefined, in a single button group the selection is not caught.

Why are the object types different? Why not a RadioNodeList of length 1 for a single radio button?

How can I check a variety of radio button groups when the number of buttons is unknown?

Here is a stripped down example:

HTML

<form action="">

  <!-- Single radio button -->
  <label for="single">Single</label>
  <input type="Radio" id="single" name="offering" value="single" checked>

  <!-- Multiple radio buttons -->
  <p>Multiple</p>
  <label><input type="Radio" id="yes" name="choices" value="Yes"> Yes </label>
  <label><input type="Radio" id="no" name="choices" value="No"> No </label>

  <div>&nbsp;</div>
  <input type="Submit" id="Submit" name="Submit" value="Continue" onclick="return checkForm(this.form)">

</form>

JS

function checkRb(rb){
  var error = '';
  var flag = 0;
  var itschecked = 0

  alert(rb);

  for (var i = 0; i < rb.length; i++){
    if (rb[i].checked){
      itschecked = 1;
    } 
  }

  if (itschecked == 0){
    error = error + "Error message \r\r";
    flag = 1;
  }

  return {flag: flag, error: error};
}

function checkForm(form){
  var error = '';
  var flag = 0;

  var ckSingle = checkRb(form.offering);
  if (ckSingle.flag == 1){
    flag = 1;
  }
  error += ckSingle.error;

  var ckMultiple = checkRb(form.choices);
  if (ckMultiple.flag == 1){
    flag = 1;
  }
  error += ckMultiple.error;

  // alert error if selection is not made
  if (flag == 1){
    alert(error);
    return false;
  }
  return true;
}
mhatch
  • 4,441
  • 6
  • 36
  • 62
  • In addition to my answer, this post might be a possible duplicate: http://stackoverflow.com/questions/7238177/how-to-detect-htmlcollection-nodelist-in-javascript .... let me know if it is and I will vote to close as duplicate – Asons Jul 16 '16 at 22:49
  • @LGSon This is a good link. Thank you for sharing. While it does have a similar problem and shows how to check if an element is a NodeList, it does not answer the question "Why are the object types different?" Additionally, this question (and your solution) involves iterating through a group of radio buttons when the element type is variable (as the title suggests)... Close, I know, but I don't know if I would call it a duplicate. – mhatch Jul 18 '16 at 14:05
  • As I don't have a good (and from a reliable source) explanation on why they are different, here is a good post about objects and nodes, maybe it give you some answers: http://stackoverflow.com/questions/9979172/difference-between-node-object-and-element-object – Asons Jul 18 '16 at 15:22

2 Answers2

0

Would updating you script to this be an option?

By check if the objects length is countable before using it you avoid the error on non array like object.

  if (rb.length > 0) {
    for (var i = 0; i < rb.length; i++) {
      if (rb[i].checked) {
        itschecked = 1;
      }
    }
  } else {
    if (rb.checked) {
      itschecked = 1;
    }
  }

Sample snippet

function checkRb(rb) {
  var error = '';
  var flag = 0;
  var itschecked = 0

  if (rb.length > 0) {
    for (var i = 0; i < rb.length; i++) {
      if (rb[i].checked) {
        itschecked = 1;
      }
    }
  } else {
    if (rb.checked) {
      itschecked = 1;
    }
  }
  
  if (itschecked == 0) {
    error = error + "Error message \r\r";
    flag = 1;
  }

  return {
    flag: flag,
    error: error
  };
}

function checkForm(form) {
  var error = '';
  var flag = 0;

  var ckSingle = checkRb(form.offering);
  if (ckSingle.flag == 1) {
    flag = 1;
  }
  error += ckSingle.error;

  var ckMultiple = checkRb(form.choices);
  if (ckMultiple.flag == 1) {
    flag = 1;
  }
  error += ckMultiple.error;

  // alert error if selection is not made
  if (flag == 1) {
    alert(error);
    return false;
  }
  return true;
}
<form action="">

  <!-- Single radio button -->
  <label for="single">Single</label>
  <input type="Radio" id="single" name="offering" value="single" checked>

  <!-- Multiple radio buttons -->
  <p>Multiple</p>
  <label>
    <input type="Radio" id="yes" name="choices" value="Yes">Yes</label>
  <label>
    <input type="Radio" id="no" name="choices" value="No">No</label>

  <div>&nbsp;</div>
  <input type="Submit" id="Submit" name="Submit" value="Continue" onclick="return checkForm(this.form)">

</form>
Asons
  • 84,923
  • 12
  • 110
  • 165
-2
<html>
<head>
<script type="text/javascript">
    function DisplayFormValues()
    {
        var chkdval='';
        var str = '';
        var elemName='';

        var elem = document.getElementById('frmMain').elements;
        for(var i = 0; i < elem.length; i++)
        {   
            if(elem[i].checked){
                str += "<BR><b>Name:</b>" + elem[i].name + ": " +  elem[i].value + " is checked.";              
            }
        document.getElementById('lblValues').innerHTML = str;   

    }

</script>
</head>
<body>
    <form id="frmMain" name="frmMain">
        <fieldset class="radiogroup"> 
        <legend>single</legend> 
        <ul class="radio"> 
            <!-- Single radio button -->        
            <li><input type="Radio" id="single" name="s1" value="single" checked><label for="single">Single</label></li>        
        </ul> 
        </fieldset> 

        <p>Multiple</p>
        <fieldset class="radiogroup"> 
        <legend>Multiple Radio</legend> 
        <ul class="radio"> 
            <li><input type="Radio" id="yes" name="m1" value="Yes"><label for="yes"> Yes </label></li>
            <li><input type="Radio" id="no" name="m2" value="No" checked><label for="no"> No </label></li>
        </ul> 
        </fieldset>     

        <!-- Triple radio buttons -->
        <p>Triple</p>
        <fieldset class="radiogroup"> 
        <legend>Triple Radio</legend> 
        <ul class="radio"> 
            <li><input type="Radio" id="yes" name="t1" value="Yes"><label for="yes"> Yes </label></li>
            <li><input type="Radio" id="no" name="t2" value="No"><label for="no"> No </label></li>
            <li><input type="Radio" id="maybe" name="t3" value="maybe" checked><label for="maybe"> Maybe </label></li>
        </ul> 
        </fieldset> 

        <!-- Quadruplet radio buttons -->
        <p>Quadruplet</p>
        <fieldset class="radiogroup"> 
        <legend>Quadruplet Radio</legend> 
        <ul class="radio"> 
            <li><input type="Radio" id="yes" name="q1" value="Yes"><label for="yes"> Yes </label></li>
            <li><input type="Radio" id="no" name="q2" value="No"><label for="no"> No </label></li>
            <li><input type="Radio" id="maybe" name="q3" value="maybe"><label for="maybe"> Maybe </label></li>
            <li><input type="Radio" id="maybe" name="q4" value="alright" checked><label for="alright"> AllRight </label></li>
        </ul> 
        </fieldset>         

        <input type="button" value="Test" onclick="DisplayFormValues();" /> 
    </form>
    <hr />
    <div id="lblValues"></div>
</body>
</html>
HiDeoo
  • 10,353
  • 8
  • 47
  • 47