Nicholas Alek
Nicholas Alek

Reputation: 273

Enable/disable a form element after checking radio button checked states

I have ten or so questions with radio buttons. They all need to be set to true, before a user can move on to another level. If and only if these ten questions have be answered to true, I'd like to have one of the elements on the form be enabled for further editing. This, I can do on the server side, but don't know how to do it in JavaScript. Any help? Much appreciated. Thanks.

<div>
<label> First Question:</label>
<label>
<input checked="checked" class="radio_buttons optional pull-right allowed" id="is_complete_and_works_true" name="project[person_attributes][is_complete_and_works]" type="radio" value="true" />Yes</label>

<label >
<input class="radio_buttons optional pull-right allowed" id="is_complete_and_works_false" name="project[person_attributes][is_complete_and_works]" type="radio" value="false" />No</label>
</div>

<div>
<label> Second Question:</label>
<label>
<input checked="checked" class="radio_buttons optional pull-right allowed" id="is_complete_and_works_true" name="project[person_attributes][researched]" type="radio" value="true" />Yes</label>

<label >
<input class="radio_buttons optional pull-right allowed" id="is_complete_and_works_false" name="project[person_attributes][researched]" type="radio" value="false" />No</label>
</div>
<div>
<label> Third Question:</label>
<label>
<input checked="checked" class="radio_buttons optional pull-right allowed" id="is_complete_and_works_true" name="project[person_attributes][is_complete_and_works]" type="radio" value="true" />Yes</label>

<label >
<input class="radio_buttons optional pull-right allowed" id="is_complete_and_works_false" name="project[person_attributes][is_complete_and_works]" type="radio" value="false" />No</label>
</div>

This code extends to several more of questions.

I've been able to select radios by doing so:

var first_ten = $(':radio[name="project[person_attributes][is_complete_and_works]"][value=true], :radio[name="project[person_attributes][researched]"][value=true], etc…);

Now, I have no idea how to iterate over each and when I click on each radio, whether yes or no, I'd like to see the result for the element to be enabled. Any thoughts much appreciated.

Upvotes: 0

Views: 3967

Answers (1)

RobG
RobG

Reputation: 147383

Something like the following will do the job:

<script type="text/javascript">

function proceed(form) {
  var el, els = form.getElementsByTagName('input');
  var i = els.length;
  while (i--) {
    el = els[i];

    if (el.type == 'checkbox' && !el.checked) {
      form.proceedButton.disabled = true;
      return; 
     }
  }
  form.proceedButton.disabled = false;
}

</script>

<form onclick="proceed(this);">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
  <input type="checkbox">
  <input type="submit" name="proceedButton" disabled>
</form>

Note that this is considered bad design as if javascript is not available or enabled, the user can never click the button. Better to deliver the form in a useful state and the, when submitted, use script to validate that the buttons are all checked and cancel the submit if they aren't.

Then at the server you can also check the state and only show the next page if the current one passes validation. If it doesn't, return the user to the first page.

That way neither you or the user care if the script works or not, the page still functions. Of course it might be a better experience if the script does work, but at least the choice isn't binary and it also gives you a simple fallback to support a very wide array of browsers with minimal effort.

So a better solution is:

<form onsubmit="reurn validate(this);" ...>
  ...
</form>

Then in the function:

function validate(form) {
  // if validateion fails, show an appropriate message and return false,
  // if it passes, return undefined or true.
}

And always validate at the server since you really have no idea what happened on the client.

Edit

Form controls don't need a name and ID, just use a name. In a radio button set, only one control can be checked, you can't check all of them.

It seems to me that what you are trying to do is to see if at least one radio button has been checked in each set. You can do that based on the code above and selecting each set as you encounter it, e.g.

function validateForm(form) {

  // Get all the form controls
  var control, controls = form.elements;
  var radios = {};
  var t, ts;

  // Iterate over them
  for (var i=0, iLen=controls.length; i<iLen; i++) {
    control = controls[i];

    // If encounter a radio button in a set that hasn't been visited
    if (control.type == 'radio' && !radios.hasOwnProperty(control.name)) {
      ts = form[control.name];
      radios[control.name] = false; 

      // Check the set to see if one is checked
      for (var j=0, jLen=ts.length; j<jLen; j++) {

        if (ts[j].checked) {
          radios[control.name] = true; 
        }
      }
    }
  }

   // Return false if any set doesn't have a checked radio
   for (var p in radios) {

     if (radios.hasOwnProperty(p)) {

       if (!radios[p]) {
         alert('missing one');
         return false;
       }
     }
   } 
} 

</script>

<form onsubmit="return validateForm(this);">
   <input type="radio" name="r0">
   <input type="radio" name="r0">
   <br>
   <input type="radio" name="r1">
   <input type="radio" name="r1">
   <br>   
      <input type="reset"><input type="submit">
</form>

Note that your form should include a reset button, particularly when using radio buttons.

Upvotes: 1

Related Questions