Hello All,

I currently am running drupal 5.3 with the webform module version 1.7. I was wondering if it was possible have certain webform components/fields (sorry, not sure what the right word is) dependent upon the user's selection of another field.

For example, I have a webform for a "for sale by owner" real estate site, which asks the user to submit his/her information including property and mortgage information. I have mortgage fields are required fields, but I wanted to add another field, where a user can state he/she does not have a mortgage.

So, ideally, the portion of the webform would look like:

----Mortgage Fieldset----
-- [] I don't have a mortgage (Checkbox that would grey-out the following fields)
-- Mortgage Balance Text Field (Required if above checkbox is not selected)
-- Mortgage Interest Text Field (Required if above checkbox is not selected)
-- Mortgage Payment Text Field (Required if above checkbox is not selected)

I know what I'm asking is sort of confusing, as it's difficult to explain. Any help on how I might be able to implement something like that is greatly appreciated.

Thanks

Comments

TUc’s picture

I want to know the answer on this one too.
TUc

yraber’s picture

You can do this by adding some JQuery magic :

* First to have a nice checkbox simply use a select component and check the "multiple" option, even if you have only one value.

Then Insert a markup component, and add this PHP code (don't forget to select input type as PHP) :

drupal_add_js (
  '$(document).ready(function(){
    $("#edit-submitted-checkbox-1-i-need-those-fields").change(function(){
      if(this.checked) {
        $("#edit-submitted-textfield1").removeAttr("disabled");
      }
      else {
        $("#edit-submitted-textfield1").attr("disabled", "disabled");
      }
    })
  });'     
  ,'inline'
);

Where
"edit-submitted-checkbox-1-i-need-those-fields" is the elementID of your checkbox
"edit-submitted-textfield1" is the element ID of the field you want to enable/disable accordingly

This can be easily adapt to enable/disable multiple fields.

And you may also have to add some additional validation to ensure the fields are filled when the checkbox is selected.

jonli447’s picture

Thanks for your reply. Do I need to install the jQuery Update module in order for this to work? For some reason, the function does not seem to be working. I followed the instructions, and double checked the element id's (php input is selected for the markup component, and the jquery function has been added to the HEAD of the page within the proper

tags. I have to admit, I'm not very familiar with jQuery, and I may have perhaps borked the syntax. This is what my script looks like (copied straight from the rendered page source):
<script type="text/javascript">$(document).ready(function(){
    $("#edit-submitted-1189360448-1195358505-check-this-box-if-you-do-not-have-any-mortgages").change(function(){
      if(this.checked) {
        $("edit-submitted-1189360448-1190821442-1190821505").removeAttr("disabled");
	$("edit-submitted-1189360448-1190821442-1190821573").removeAttr("disabled");
	$("edit-submitted-1189360448-1190821442-1190821602").removeAttr("disabled");
	$("edit-submitted-1189360448-1190821442-1190821630").removeAttr("disabled");
      }
      else {
        $("edit-submitted-1189360448-1190821442-1190821505").attr("disabled", "disabled");
	$("edit-submitted-1189360448-1190821442-1190821573").attr("disabled", "disabled");
	$("edit-submitted-1189360448-1190821442-1190821602").attr("disabled", "disabled");
	$("edit-submitted-1189360448-1190821442-1190821630").attr("disabled", "disabled");
      }
    });
  });</script>
Thanks again
yraber’s picture

After skimming through your post, I saw that you forgot some hash (#) characters.

$("edit-submitted-1189360448-1190821442-1190821573").removeAttr("disabled");
should be
$("#edit-submitted-1189360448-1190821442-1190821573").removeAttr("disabled");

... and so on.

FYI, the hash means the element is selected by ID (more here http://docs.jquery.com/Selectors).

jonli447’s picture

Thanks, that's what I was missing. :-)

Here's the php I stuck in the markup component:

<?php
drupal_add_js (
  '$(document).ready(function(){
    $("#edit-submitted-1189360448-1195358505-check-this-box-if-you-do-not-have-any-mortgages").change(function(){
      if(this.checked) {
	$("#edit-submitted-1189360448-1190821442-1190821505").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821573").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821602").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821630").attr("disabled", "disabled");
      }
      else {
	$("#edit-submitted-1189360448-1190821442-1190821505").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821573").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821602").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821630").removeAttr("disabled");
      }
    });
  });'    
  ,'inline'
);
?>

So, now the markup works, and the "required" fields are greyed out when the checkbox is selected. Now it's part two, figuring out how to unset the "required" component, so that when required fields are greyed out, they are no longer required. I'll look into the webform/drupal api's some more to see how I can do this. Thanks again, I greatly appreciate your help.

hp9’s picture

Where do I find the ElementID for a webform component?
Is it different from the field key?
Sorry, I'm new at this.

jonli447’s picture

Hello again,

I almost got it working (thanks yraber :-) ). The part I'm still stuck on, is what webform function (or drupal api possibly) is responsible for validating required fields. Basically, I've got the jquery part working, but I want to see if I can manage to get the Mortgage components to be required if and only if the "I don't have a mortgage" checkbox is not selected. The other part is a bit of cosmetics, but I'd also like to have it so that if those mortgage components are required (when the checkbox is not selected), they are marked with a red asterisk (like normal "required component" behavior). Furthermore, if the components fail validation, the components are then highlighted with a red box (also normal "required component" behavior).

I dove a little bit into the webform module a bit to see how normal "required component" behavior worked, and it seems that when the before the webform is rendered, the module creates an array for each component. In the array is a "mandatory" variable which is set to "0" for disabled, and "1" for enabled. I thought about adding a routine in additional_validation to change this variable depending on if the checkbox was selected, but it seemed unwise as the webform module determines this var from the component SQL database.

So, I looked at bit further, and it seems that the webform module adds extra form elements to mandatory components. These elements add the red highlighting effect (upon failed validation) and the red asterisk. The validation error itself uses the drupal form_set_error api. What I could not figure out is what function was responsible actually "making" required components.

To recap, I'm now trying to see if I can make my mortgage webform components required if the "I don't have a mortgage" checkbox is not checked. I'd like the behavior also to be similar to how the webform module normally handles required components (with highlighting fields the fail validation, red asterisk, etc.). Any help in what direction I take to accomplish this task is greatly appreciated (i.e. do I need to create a whole much of custom markup components or is there a simple api I could use?)

Thanks a lot in advance (and a special thanks again to yraber),

Jon

yraber’s picture

Here is an example of addition validation that I used to do the trick (don't put the fields as mandatory, because this will be handled by this script) :

<?php
$filled = array();

/* Retrieve all filled fields */
foreach ($form_values['submitted'] as $field_id => $value) {  
  if($value) {
    $component = $node->webformcomponents[$field_id];
    $filled[$component['name']] = $value;
  } 
}
	
/* Check mandatory values */
if(($filled['Mortgage_1) && (!$filled['mortgage_option_1'])) {
  form_set_error('submitted][fieldset_mortgage_1][mortgage1_amount','Please fill mortage 1 amount');
}

?>

The crutial part is here :

form_set_error('submitted][fieldset_mortgage_1][mortgage1_amount','Please fill mortage 1 amount');
jonli447’s picture

I finally managed to get the validation part of the code to work. In addition, I got jquery to mark the mortgage fields if the checkbox was disabled, even if validation failed. Thanks again yraber for your help. My markup looks something like this:

<?php
drupal_add_js (
  '$(document).ready(function(){
    if($("input[@name=\'submitted[1189360448][1195358505][check_this_box_if_you_do_not_have_any_mortgages]\']:checked").val()) {
      $("#edit-submitted-1189360448-1190821442-1190821505").attr("disabled", "disabled");
      $("#edit-submitted-1189360448-1190821442-1190821573").attr("disabled", "disabled");
      $("#edit-submitted-1189360448-1190821442-1190821602").attr("disabled", "disabled");
      $("#edit-submitted-1189360448-1190821442-1190821630").attr("disabled", "disabled");
    }

    $("#edit-submitted-1189360448-1195358505-check-this-box-if-you-do-not-have-any-mortgages").change(function(){
      if(this.checked) {
	$("#edit-submitted-1189360448-1190821442-1190821505").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821573").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821602").attr("disabled", "disabled");
	$("#edit-submitted-1189360448-1190821442-1190821630").attr("disabled", "disabled");
      }
      else {
	$("#edit-submitted-1189360448-1190821442-1190821505").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821573").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821602").removeAttr("disabled");
	$("#edit-submitted-1189360448-1190821442-1190821630").removeAttr("disabled");
      }
    });
  });'    
  ,'inline'
);
?>

(I know, the field identifiers are still non-descriptive, I have to rewrite another program before I can make them better).

I was wondering though, is it possible to use jquery to modify the "label for=" to include the <span class="form-required" title="This field is required.">*</span></label> part into the label for required fields?

For example, if the checkbox was not selected (thus the mortgage fields are required), then the labels for each mortgage field would look something like:
<label for="edit-submitted-1189360079-1190819585">Basement: <span class="form-required" title="This field is required.">*</span></label>
Otherwise, if the checkbox was selected, and the fields were disabled (thus not required), the field labels would look like:
<label for="edit-submitted-1189360079-1190819585">Basement: </label>

It's not a big deal, since functionality wise, everything works. However, I thought it would be neat to add the asterisks if the fields are required. Thanks.

aterchin’s picture

this is fantastic. great question jonli447, great answer yraber. i've bookmarked this page for further reference if ever i need jquery to do something similar.

armyofda12mnkeys’s picture

Did you ever figure out the complete solution to this?

like for validation, the above php code i assume gets put into the a code markup type, but isnt the required/validation processing done at this point and we are just rendering the form? how did you get it to validate before rendering the page?

I wanted to make a checkbox and a subfieldset (hidden by default) so that if the checkbox selected, the subfieldset is unhidden.
The subfieldset has many questions underneith it which would then be required. All I have so far is the jquery to do the show/hide stuff.
i was wondering how validation is done, as it seems like the code markup gets rendered after all the processing. so how does one 'stop' the processing? In the same markup layer which is echoing the jquery?

Btw,
i think you want some thing like this to add the required things to those optional fields (for me i add this jquery when the checkbox is checked, and hence they beccome required):
$("label[for=\'required-if-checked1\']").append('*');
$("label[for=\'required-if-checked2\']").append('*');
$("label[for=\'required-if-checked3\']").append('*');

$("label[for=\'required-if-checked1\'] span").remove();
$("label[for=\'required-if-checked2\'] span").remove();
$("label[for=\'required-if-checked3\'] span").remove();

still have to figure out how to add validation, and default value on the form (like when arriving on the page, my extra fields should be disabled unless checkedbox is checked(which could happen if its default value of checkbox is checked or was submitted be4 and checked, or just submitted and is checked) )

EDIT: i think i got it, the webform advanced controls were collapsed and i thought it was expanded already. :), maybe ill upload full example to help someone get started

armyofda12mnkeys’s picture

So here are the steps i figured out thanks to help above, seems functional and working for me, hope it helps others out:
In my webform, i want a checkbox field that when checked unveils 2 mandatory textfields and an optional textfield under it.

I just create a main fieldset form componant called 'business' to hold all my fields in this question.
I add a markup code form componant first which will be modified later. be sure to set its input filter as php filter.
I create a checkbox form componant called 'do_you_enjoy_your_job' with yes and no options. The checkbox isnt mandatory as having it unchecked is valid option of course.
I create a subfieldset after this called 'optional_enjoy' that will hold 3 textfields, notice on teh view source of the webform its css ID is 'webform-component-optional_enjoy'.
Then create 3 textfields underneith this subfieldset. i do not set them as mandatory via GUI as this will be custom validated only if checked.
I look at the source of the form, i see the checkbox fields name is called 'submitted[business][do_you_enjoy_your_job][yes]'.
The 3 textfields i see are called:
submitted[business][optional_enjoy][if_yes_why_do_you_love_it]
submitted[business][optional_enjoy][if_yes_why_do_you_like_it]
submitted[business][optional_enjoy][if_yes_why_do_you_do_it]
I will use these to target the script via javascript later.

So my markup code I add this:


echo '
<script type="text/javascript">

	//functions to show/enable and hide/disable specific fieldset
	function showValues(){
        $("#webform-component-optional_enjoy").show();
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_love_it]\']").removeAttr("disabled");
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_like_it]\']").removeAttr("disabled");
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_do_it]\']").removeAttr("disabled");

		//only first 2 subquestions are required
         $("label[for=\'edit-submitted-business-optional-enjoy-if-yes-why-do-you-love-it\']").append(\'<span class="form-required" title="This field is required.">*</span>\');
        $("label[for=\'edit-submitted-business-optional-enjoy-if-yes-why-do-you-like-it\']").append(\'<span class="form-required" title="This field is required.">*</span>\');		
	}
	function hideValues(){
        $("#webform-component-optional_enjoy").hide();
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_love_it]\']").attr("disabled","disabled");
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_like_it]\']").attr("disabled","disabled");
        $("input[name=\'submitted[business][optional_enjoy][if_yes_why_do_you_do_it]\']").attr("disabled","disabled");
			
		//only first 2 subquestions are required
        $("label[for=\'edit-submitted-business-optional-enjoy-if-yes-why-do-you-love-it\'] span").remove();
        $("label[for=\'edit-submitted-business-optional-enjoy-if-yes-why-do-you-like-it\'] span").remove();
	}

    $(document).ready(function(){

    $("input[name=\'submitted[business][do_you_enjoy_your_job][yes]\']").click(function(){
      if(this.checked) {//check events checked property... if they just checked it, show the hidden fieldset, undisable the textfields, and add the required * at end of each field. If above condition doesnt work might need to get DOM node directly $("...your target").get(0).checked (just noticed not sure why i have access to that property hehe).
		showValues();
      }
      else {//if just unchecking, hide the options and disable them, and get rid of the required * as its not required (guess u dont need it, as its hidden anyway, but eh). 
		hideValues();
       }
    });

  });


</script>
';

//also check to see what default state of subfields should be, if the  checkbox is checked when arrive to the page (via a result submission page or an error after submit), before any onclick events.
echo('
	<script type="text/javascript">
	$(document).ready(function(){	
	
		var checkbox = $("input[name=\'submitted[business][do_you_enjoy_your_job][yes]\']");
		
		if( checkbox.get(0).checked )//need checked property of DOM node
		{
			showValues();
		}
		else
		{
			hideValues();
		}
	});
	</script>
');
//end of code markup form component











THIS GOES INTO THE custom data validation code added to 'Webform advanced settings' in the 'Additional Validation' field on the Webform Settings Configuration page:
<?php

$custom_submitted = $_POST['submitted'];
if(  ($custom_submitted['business']['do_you_enjoy_your_job']['yes']=='yes')  )
{
	//will error the form, show the message at top and redden the border of offending fields
	if( trim($custom_submitted['business']['optional_enjoy']['if_yes_why_do_you_love_it']) == '' )
	{
	form_set_error('submitted[business][optional_enjoy][if_yes_why_do_you_love_it]','if_yes_why_do_you_love_it is required.');
	}
	if( trim($custom_submitted['business']['optional_enjoy']['if_yes_why_do_you_like_it']) == '' )
	{
	form_set_error('submitted[business][optional_enjoy][if_yes_why_do_you_like_it]','if_yes_why_do_you_like_it is required.');
	}	
}

ill prob add Save Draft feature and see if theres an option in this componant to only allow 1 form submission per user.
Then itll be perfect

davidhernandez’s picture

To armyofda12mnkeys, this worked great. Thank you for posting the code. I had to change it to make use of a select box, instead of a check box, so I changed it to the following:


$(document).ready(function(){
      $("select[name=\'submitted[your_id]\']").change(function(){
        if(this.selectedIndex==6) {  // I just looked for the index value of the option I wanted. Below, I had to use the actual value.
          showValues();
        }
        else {
          hideValues();
        }
      });
});

$(document).ready(function(){   
       var selectval = $("select[name=\'submitted[your_id]\']");
       if(selectval.val()=="Some Value") { // I had trouble accessing the selected index value, don't know why. 
         showValues();
       } 
       else {
         hideValues();
       }
});

Thanks for all the info. This help me tremendously, and was exactly what I needed.

bionichb’s picture

hi
one month has passed since the last post on this thread. is there any new solution to this problem!? The mulltiform module seems to provide similar functionality (mainly the possibility of creating form elements). However the conditional forms issue doesn't seem to be addressed anywhere..

thanks for all the previous info

davidw’s picture

Great!
Thanks for posting the code! I can really use this.

davidhernandez’s picture

Thanks for the info yraber. This was very helpful. One typo: "$node->webformcomponents[$field_id]" should be "$node->webform['components'][$field_id]" Also, I used "$component['form_key']" for the array index, which allowed me to compare the machine-readable names. Otherwise, I would have to use to human-readable ones which were very long on my form. This saved me a lot of fiddling. Thanks!

bribas’s picture

I got this working, Thanks!!! Is there any way to have this collapse a fieldset?

bionichb’s picture

hi
one month has passed since the last post on this thread. is there any new solution to this problem!? The mulltiform module seems to provide similar functionality (mainly the possibility of creating form elements). However the conditional forms issue doesn't seem to be addressed anywhere..

thanks for all the previous info

bionichb’s picture

hi
one month has passed since the last post on this thread. is there any new solution to this problem!? The mulltiform module seems to provide similar functionality (mainly the possibility of creating form elements). However the conditional forms issue doesn't seem to be addressed anywhere..

thanks for all the previous info

UNarmed’s picture

Would it be possible to make divs display:none with the above method? I dont just want to disable fields i want to hide there entire container so that the label also does not show?

Some example code of how i would go about this would be absolutely amazing!

UNarmed’s picture

I have most of this figured out but i am still having a couple of problems. Im passing a value from views to the form. Basically i need certain fieldsets to only show up when certain terms are passed to the view.

<?php
drupal_add_js (
  '$(document).ready(function(){
    $("#edit-submitted-product-type-2-Printer").change(function(){
      if(this.checked) {
    $("#webform-component-cartrage_information").show();
      }
    });
  });'   
  ,'inline'
);
?>

I need to have #webform-component-cartrage_information not displaying untill the box is ticket, currently if i pass any other value to the form the box stil displayes? Please guys im way out of my depth here but this is really important and any help would be appreciated.

UNarmed’s picture

Ok i managed to get something that works for me. The div has a style="display:none" and the i have this code

<script type="text/javascript" id="demoscript">
       $(function(){
               if (document.location.href.indexOf('name=Printer') > 0)
$("#webform-component-cartrage_information").show();
       });
</script> 

That displays the div id a certain url parameter is present. Haha looks like i went about this all wrong trying to adapt the code posted here by other people. Still great for future reference =]