Unexplained (buggy?) behavior of drupal_process_states with checkboxes in Drupal 7

by Yury   Last Updated April 15, 2019 01:07 AM

I have 3 checkboxes named A, B, C. My desired behavior is as follows: if, and only if, both A and B are unchecked, then C becomes checked. Inversely, if either A or B are checked, C becomes unchecked.

I originally had the following definition under '#states' for C:

'checked' => array(
    ':input[name="A"]' => array('checked' => FALSE),
    ':input[name="B"]' => array('checked' => FALSE),
)

This works fine when both A and B start out as checked on the form, so C only becomes checked when I uncheck both A and B.

The problem is, this doesn't work when e.g. only A starts out as checked. In that scenario, unchecking A does NOT trigger C to become checked.

So I tried the following, which DOES work when only one of A or B starts out as checked - but NOT if both are checked:

'checked' => array(
    ':input[name="A"]' => array('!checked' => TRUE),
    ':input[name="B"]' => array('!checked' => TRUE),
)

I honestly don't even understand how this is different from my original code above (and I haven't found any documentation that would explain it), but my guess is that maybe '!checked' => TRUE matches an element that has not been explicitly checked the user (but its current state is unknown), while 'checked' => FALSE only matches something that was explicitly unchecked. And btw, how/why is 'checked' => FALSE different from 'unchecked' => TRUE, because the latter does NOT have the same effect in my testing?!

But anyway, after trying a bunch of different things, I came up with the following - which still works when only A starts out as checked:

'checked' => array(
    ':input[name="A"]' => array('checked' => FALSE),
    ':input[name="B"]' => array('checked' => FALSE),
    ':input[name="A"]' => array('!checked' => TRUE),
    ':input[name="B"]' => array('!checked' => TRUE),
)

BUT - this still does NOT work when both A and B start out as checked. In that scenario, unchecking either A or B still triggers C to become checked. And here's the big question: HOW CAN ADDING CONDITIONS TO AN AND CLAUSE TRIGGER AN EVENT THAT IS NOT TRIGGERED BY A SUBSET OF THOSE CONDITIONS?!? In other words, if I comment out conditions 3 and 4 above, the code works when A and B start out checked: C doesn't become checked until I uncheck both A and B. But as I said above, with lines 3 and 4 added, it only takes unchecking A OR B to trigger C to become checked, which is NOT what I want!!

So my actual question is twofold: how/why does this happen with 2 of the 4 conditions, and of course, how can I achieve the desired effect, as stated in my first paragraph?

Tags : 7 forms


Related Questions


Updated July 06, 2015 13:03 PM

Updated June 24, 2016 08:03 AM

Updated May 21, 2015 22:03 PM

Updated February 22, 2016 05:03 AM

Updated May 19, 2016 07:46 AM