This feature request is to conditionally set other component values in a general way. It is a generalization of the original request below.

Original Issue:
Similar to #1885056: Conditional actions: required / optional

It would be nice to have the option to have a conditional for checking/unchecking checkbox fields depending on the value of one or more other fields on the webform.

I haven't looked into the code of the existing conditionals show/hide yet, but i know that the Drupal #states attribute allows checked/unchecked so it would seem to me that this is something quite similar.

I'm assuming patches are welcome ;)

Comments

danchadwick’s picture

Yes, patches are welcome on this topic. #states would not be the way to do it. Except for show/hide (which you already have), they require a trip to the server, which definitely want to avoid. There is a very small amount of existing code that anticipates conditionals that do things other than show/hide.

Conditionals are surprisingly complicated. They interact with both save-as-draft and multi-page. In addition, there is an open issue about performance problems related to having a lot of conditional. I believe it related to the definition, not the use. I haven't looked into it closely.

oenie’s picture

I've looked into the code and it does look pretty complicated, mostly because the conditional code seems really geared toward the show/hide conditionals.
Even the function title that does the checking actually returns a showComponent variable, as well as mentions 'show/hide component' in it's documentation.
I'm not sure wether this functions needs to be rewritten to handle extra conditional actions, or that another function needs to be made.

The show/hide function is used on several occasions to actually show/hide a component, so rewriting it would interfere with a lot of calls.

I will see if i can find a solution for it (time and code-wise), taking your comments in consideration, Dan.
However it might be that for the time being i will have to introduce some custom alter code since i currently only have one case that needs these extra conditionals.
But i can see potential extra cases in the future, and i can hardly imagine that no one else has come across this issue.

Thanks for the reply !

danchadwick’s picture

With the completion of the conditional engine (WebformConditionals class), this feature request is much more doable. I would like to know more about the use case. Setting a component would effectively disable it for as long as the input conditions are true. For example:

IF Color = 'green' THEN SET 'Blood Color' to 'Vulcan'

So when Color is green, any attempt by the user to change the Blood Color would be defeated. To avoid frustration, the field should probably also be disabled when it is being set. Only when Color isn't green could the use change the Blood Color field.

Would this work for your use case?

danchadwick’s picture

Title: Conditional actions: checked / unchecked » Conditional actions: set values, checked, unchecked
Issue summary: View changes
danchadwick’s picture

Status: Active » Needs review
StatusFileSize
new22.49 KB

This patch implements a "Set to" conditional action. It allows values to be set for the following components:

  • hidden
  • markup (subject to filter_xss_admin)
  • select - radio buttons
  • select - check boxes (multiple)
  • select - list box
  • select - list box (multiple)
  • text area
  • text field

Notable it does not implement date or time, although patches are welcome for those.

When set, the target component cannot be changed by the user (disabled or readonly, as appropriate). If the component is also hidden ("isn't shown"), that trump the any value set. More than one conditional can set the same conditional. If more than one is active at a time, the result in undetermined.

For select components, multiple values may be specified separated by commas. The key is given, not the user-facing text.

This is fairly complicated code and deserves testing.

danchadwick’s picture

StatusFileSize
new22.75 KB

Here an update that add support for email components.

Status: Needs review » Needs work

The last submitted patch, 6: webform-conditional_set-2415849-6.patch, failed testing.

danchadwick’s picture

Status: Needs work » Needs review

Test failure -- if genuine -- is related to tests not being updated for new token substitution rules.

danchadwick’s picture

Those 4 fails pass when run locally with drush.

danchadwick’s picture

Status: Needs review » Fixed

#6 committed to 7.x-4.x.

danchadwick’s picture

Version: 7.x-4.x-dev » 8.x-4.x-dev
Status: Fixed » Patch (to be ported)

Needs port to D8. Of the four conditional patches to be ported, apply 5th.

  • DanChadwick committed fc964b5 on 7.x-4.x
    Issue #2415849 by DanChadwick: Conditional actions: set values, checked...
fenstrat’s picture

Version: 8.x-4.x-dev » 7.x-4.x-dev
Status: Patch (to be ported) » Fixed

Committed and pushed to 8.x-4.x. Thanks!

  • fenstrat committed f4d2f9d on 8.x-4.x authored by DanChadwick
    Issue #2415849 by DanChadwick: Conditional actions: set values, checked...

The last submitted patch, 5: webform-conditional_set-2415849-5.patch, failed testing.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

vakeesan26’s picture

is it possible to conditionally set one component value to other component (like delivery address same as billing)
(currently only able to set a static text value)

danchadwick’s picture

Re #17. No, and not likely to be implemented by me.

gregori.goossens’s picture

Hi,

i have some trouble when i conditionally set value to a radio component.
The problem seems to be in webform.js in $.fn.webformVal function.

  $.fn.webformVal = function (values) {
    this.each(function () {
      var $this = $(this);
      var value = $this.val();
      var on = $.inArray($this.val(), values) != -1;
      if (this.nodeName == 'OPTION') {
        $this.webformProp('selected', on ? value : false);
      }
      else {
        $this.val(on ? [value] : false);
      }
    });
    return this;
  };

When we use radio webform component input type radio are created and safe_key store in value attribute.

If i use condition on first component to set second radio component, the webformVal function select (with $this.val(...) ) safe_key target in condition but also set value to false for the other choice.

Then if you change first component (so change condition) the second component safe_key store in value attribute have been erased to false.

Maybe we should set the value only if on is true :

  else {
      if(on) $this.val([value]);
  }

What do you think about it ?

Thanks

Sam77’s picture

Hi,

Info in #15 really helped me with my case.
but it also give me error while submitting.

Basically, I have a checkbox for label1 and 3 checkboxes for label2.
I have a "conditional" that when, label1 checkbox is selected, check all the checkboxes of label2.
so I have "set to" to 1,2,3

when I submit, I get an error
"an illegal choice has been detected.."

after all experiments, I know that its due to the comma separated values that I am using.
if I use 1 instead of 1,2,3 then only 1 checkbox is getting selected and submission goes through without any issue.

Please help.

Thanks.

rakun’s picture

#20 I have same problem. My workaround is ..

in _webform_client_form_validate function instead of

if (is_array($elements['#value'])) {
          $value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
          foreach ($value as $v) {
            if (!isset($options[$v])) {
              form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
              watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
            }
          }
        }

I used

if (is_array($elements['#value'])) {
          $value = $elements['#type'] == 'checkboxes' ? array_keys(array_filter($elements['#value'])) : $elements['#value'];
          if($elements['#type'] == 'checkboxes' || $elements['#type'] == 'select') {
            $value_str = $value[0];
            $value_str = str_replace(' ', '', $value_str);
            $value = explode(',', $value_str);
          }
          foreach ($value as $v) {
            if (!isset($options[$v])) {
              form_error($elements, t('An illegal choice has been detected. Please contact the site administrator.'));
              watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
            }
          }
        }

code handles value in conditional field as array for checkboxes and select component.