4

I've used the FAPI #states system before to show/hide conditional fields. It's great.

However, when I am trying to show a field based on another field's value, I'm running into a problem. The documentation for this only explains how to show/hide a field based on whether my independent field has a particular value. In my case, I don't care what the exact value is, but if it has multiple values selected from a select list, I'd like to show my dependent field, and hide it otherwise.

Does the FAPI #states system support this? If so, where can I find the syntax for how to use it?

  • have you tried array('!value' => 'whatever -none- is in your select') ? – Jimajamma Jan 17 '14 at 22:47
  • I don't just want to show the dependent field if the independent field has a value, it has to be multiple values selected. Also, I'm not sure what '!value' would mean. The opposite of the value is none? Doesn't really make sense. Anyway, "empty" and "filled" are already valid remote states. – beth Jan 17 '14 at 23:33
  • I didn't understand your requirement that multiple values had to be selected. I was thinking it would be the case if any value (or more) had been actually selected (meaning value doesn't equal the -none- value not selected, sorry if double negatives), and saw this api.drupal.org/comment/24708#comment-24708 but now that you mention multiple selections are required the answer there might make more sense as well. – Jimajamma Jan 18 '14 at 2:07
3

I cannot see how #states can meet a condition like this. The right side of the condition array always requires a literal value. In my opinion this use case requires custom JavaScript. Something like this should do it (obviously adapt the selectors etc.).

(function ($) {
  function update($select_element, $target) {
    var count = $('option:selected', $select_element).length;
    if (count > 1) {
      $target.show();
    }
    else {
      $target.hide();
    }
  }

  Drupal.behaviors.MYMODULE = {
    attach: function (context, settings) {
      $('#-MY-SELECT-FIELD', context).once('MYMODULE', function () {
        var $target = $('#-MY-TARGET-FIELD');
        var $select_element = $(this);

        // Update once on attach-behaviors.
        update($select_element, $target);

        // Update whenever select element changes.
        $select_element.change(function() {
          update($select_element, $target);
        });
      });
    }
  };
}(jQuery));
  • It is indeed possible with #states. See #735528 for details. – berliner Jan 18 '14 at 23:33
  • 1
    @berliner: I agree that your solution works when the reference values are known (i.e. literal values). However as I understand the question, the condition translates to at least X of N options selected where X=2 which you cannot express using #states. – znerol Jan 19 '14 at 12:01
  • Your right, I think I misunderstood the question then. – berliner Jan 19 '14 at 12:34
3

You should be able to define something like this:

'visible' => array(
  array(
    ':input[name="ELEMENTNAME"]' => array(
      array("value" => 'VALUE_1'),
      array("value" => 'VALUE_2'),
    ),
  ),
),

See this question for more details

  • This doesn't answer my question. It would change the state if ANY of those was selected, even if it were just one, or am I misunderstanding? – beth Jan 20 '14 at 14:10
  • You could define multiple value combinations too, that's why it's arrays. But as can be seen in the comments to the accepted answer, I misunderstood the question a little. – berliner Jan 20 '14 at 14:35
  • I guess this would work if I listed every possible combination of two or more choices. Upvoting for that. – beth Jan 20 '14 at 17:34
1

Does the FAPI #states system support this?

Core can't do it out of the box, but you can extend or even override it. There is great example: Extending Form API #states with regular expressions

In your case I suggest to create new state "select_not_empty" which will be TRUE when one or more items selected in select list.

(function ($) {
  Drupal.behaviors.statesModification = {
    weight: -10, // Don't forget to enable https://drupal.org/project/behavior_weights module.
    attach: function(context, settings) {
      if (Drupal.states) {
        // Custom state for select list.
        Drupal.states.Trigger.states.select_not_empty = {
          'change': function () {
            return $('option:selected', this).length ? true : false;
          }
        }
      }
    }
  }

}(jQuery));

Now you can use this new state as usual:

'#title' => t('Something selected!'),
'#type' => 'checkbox',
'#states' => array(
  'checked' => array(
    array(
      'select[name^="select"]' => array(
        'select_not_empty' => TRUE,
      ),
    ),
  ),
)

This method requires Behavior weights module.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.