I would expect a '#states' property to work with fieldsets as with any other form element, but in the following example only $form['high_school']['tests_taken'] is affected by the change of the select element even though the #states property is the same in each:

function form_example_states_form($form, &$form_state) {
  $form['student_type'] = array(
    '#type' => 'select',
    '#options' => drupal_map_assoc(array(t('High School'), t('Undergraduate'), t('Graduate'), t('None of these'))),
    '#title' => t('What type of student are you?')
  );

  $form['high_school'] = array(
    '#type' => 'fieldset',
    '#title' => t('High School Information'),
    '#states' => array(
      'visible' => array(
        'select[name=student_type]' => array('value' => t('High School')),
      ),
    ),
  );
  $form['high_school']['tests_taken'] = array(
    '#type' => 'checkboxes',
    '#options' => drupal_map_assoc(array(t('SAT'), t('ACT'))),
    '#title' => t('What standardized tests did you take?'),
    '#states' => array(
      'visible' => array(
        'select[name=student_type]' => array('value' => t('High School')),
      ),
    ),

  );
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sun’s picture

sun’s picture

#667944: Javascript #states cannot hide fieldsets, radios, checkboxes was supposed to fix this, and it actually works for me. So let's figure what's wrong in that example code.

rfay’s picture

FileSize
1.27 KB

Here's a complete working example (that doesn't work) to demonstrate this. If there's a problem with the example, that will make me happy.

This demonstrates three different issues, so use the 'Bug Demo: #states hiding fieldset' menu entry.

JohnWoltman’s picture

The following code works with textfields, but not with fieldsets.

$conditions = array(
  'visible' => array( ':input[#edit-myradios]' => array('checked' => true) )
);

// radio buttons control visibility of other elements
$form['myradios'] = array(
  '#type' => 'radios',
  '#title' => '',
  '#options' => array( 'new' => t('New'), 'existing' => t('Existing') )
);

// sample textfield that shows/hides based on myradios state.
$form['mytextfield'] = array(
  '#type' => 'textfield',
  '#title' => 'My Textfield',
  '#states' => $conditions
);

$form['myfieldset'] = array(
  '#type' => 'fieldset',
  '#title' => 'My fieldset',
  '#states' => $conditions
);
rfay’s picture

Title: #states doesn't work with fieldsets » #states doesn't can't hide/show fieldsets

#states does work with expanding fieldsets, for example, and works with visibility of other fields (as in #4) but doesn't do visible/invisible with fieldsets.

sun’s picture

Status: Active » Reviewed & tested by the community
Issue tags: +Quick fix, +FAPI #states
FileSize
1.19 KB

0) This should have been fixed via #667944: Javascript #states cannot hide fieldsets, radios, checkboxes, but only was partially. (see below)

1) Your selector is totally bogus:

        ':input[hide_fieldset]' => array('checked' => TRUE),

2) You do not need the second #states on the inner textfield within the fieldset.

3) Fieldsets only get a .form-wrapper CSS class, when they are #collapsible. Attached patch fixes that and therefore this entire issue.

4) I tested, so RTBC.

rfay’s picture

FileSize
1.54 KB

Thanks for your work on this sun!

I agree that this is RTBC - and a welcome one.

The demonstration module (with your note from 1) fixed) is attached, to make this easy to test. As you can imagine, I found the bug in other code, then foobared in the demo module in such a way as to make double-bug. Thanks for catching it.

The purpose for the second #states, of course (which is still in there) was to show that the basic construct worked correctly, just not on fieldsets. It still shows that without your patch.

I tested too, so agree that it's RTBC. If the question of adding demonstration code had been settled I'd add some, but since you're on such a roll I don't want to put anything in the way!

Thanks,
-Randy

rfay’s picture

Title: #states doesn't can't hide/show fieldsets » #states can't hide/show fieldsets
webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD.

JohnWoltman’s picture

Works great for me, thanks Sun!

Status: Fixed » Closed (fixed)

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

Berdir’s picture

In case someone is looking for this here, it doesn't seem to work when the fieldset is in a vertical tab. Not sure if that is a bug or not.

Basically, it only works if you're on the corresponding vertical_tab and then for example toggle a checkbox. Then, the *content* of the vertical tab is correctly hidden/shown, but that's about it.

Berdir’s picture

Ok, I did some hacking and wrote a patch that seems to work for me, issue is #1148950: Applying #states to a vertical tab does not update the vertical tabs menu

mattew’s picture

Issue summary: View changes

I encountered the same issue, trying to hide a fieldset (collapsible = TRUE, collabsed = FALSE) with a checkbox, and I found the solution: The fieldset have to explicitly provide an #id attribute.

Maybe this should be pointed out in the documentation.

bbinkovitz’s picture

I posted this on the wrong issue. Someone with delete powers please remove. Thanks/sorry.

Ronino’s picture

I can confirm like #14 that this only works if the fieldset has an #id set.

tomasdev’s picture

This worked for me on Drupal 8 (different hook)

function my_modules_field_group_build_pre_render_alter(&$element) {
  $behavior_selector = ElementHelper::inputJQuerySelector($element['field_dropdown_behavior']['widget']);

  if (isset($element['group_standard_confirmation'])) {
    // Add form states to the field group.
    $element['group_fieldset1']['#states'] = [
      'visible' => [
        $behavior_selector => ['value' => 'dropdown-value'],
      ],
    ];
  }
}

as taken from https://www.drupal.org/project/field_group/issues/1053174#comment-12234371

arunkumarmishra’s picture

I am using #states for in a node form, with this code

$form[field_registration_start_date]["widget"][0]['#states'] = [
'visible' => [
':input[name=field_registration_date[value]"]' => ['checked' => TRUE]
],
];

Gomez_in_the_South’s picture

The example from #17 didn't work for me in D9 (the hook didn't seem to be called).

What worked for me instead was using hook_field_group_form_process instead, as per this comment.