I'm doing what I think is a pretty simple form alter to utilize D7's form_state, so I can conditionally show a field group, its like this:

function antonelli_form_endoscopy_record_node_form_alter(&$form, &$form_state) {
	
  // fieldset colonoscopy
  $form['#fieldgroups']['group_colonoscopy'] = array(
    '#states' => array(
      'visible' => array(
        '#edit-field-procedure-und' => array('value' => t('colonoscopy')),
      ),
    ),
  );
  
  // fieldset gastroscopy
  $form['#fieldgroups']['group_gastroscopy'] = array(
    '#states' => array(
      'visible' => array(
        '#edit-field-procedure-und' => array('value' => t('gastroscopy')),
      ),
    ),
  );

  // print kpr($form);
}

The problem is the fieldgroups disappear entirely from the form, not just hidden, they are not printed at all, and I don't really understand why not because I have done this before with another form.

Any pointers much appreciated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Jeff Burnz’s picture

I should mention that when I run this code I get a bunch of php notices all pertaining to field_group_field_group_pre_render(), such as:

# Notice: Trying to get property of non-object in field_group_field_group_pre_render() (line 494 of C:\Users\Jeff\Sites\Friends and Family Sites\Chris Daynes\Patient records site\drupal-7.0\sites\all\modules\field_group\field_group.module).
# Notice: Trying to get property of non-object in field_group_field_group_pre_render() (line 528 of C:\Users\Jeff\Sites\Friends and Family Sites\Chris Daynes\Patient records site\drupal-7.0\sites\all\modules\field_group\field_group.module).
Stalski’s picture

I just tried it and it works here. Cool trick you learned me.
But about the problem you have. The notices are not good at all and indicate that the group that was given to the pre_render does not exist.
Difficult to say why that would occur. Did you do something custom for fieldgroups?

Stalski’s picture

ah I think you need to do like i did:

$form['#fieldgroups']['group_colonoscopy'] ['#states'] = array(
    'visible' => array(
      '#edit-field-procedure-und' => array('value' => t('colonoscopy')),
    ),
  );

As the fieldgroup will be gone ofcourse with everything in it. Maybe that is what your form alter does and why you see the missing group given. Does that fix your problem?

- Edit

Jeff Burnz’s picture

Actually using [#states] gives a fatal error :)

The only thing different I am doing is that both form elements are nested inside a vertical tab (done with Fieldgroup module), but I wouldn't think that makes a difference?

I tried just changing the #title of the fieldset inside the form alter and even with just that the fieldset does not print, such as:

  // fieldset colonoscopy
  $form['#fieldgroups']['group_colonoscopy'] = array(
    '#title' => t('this should work...'),
  );

So either I am doing something wrong with the form alter or something is going wrong inside fieldgroup module?

Jeff Burnz’s picture

FileSize
38.02 KB

Just adding a small picture to show what I am trying to achieve here - you will see there is a select list field with two options, when one option is chosen the related fieldset should show and the other one remain "hidden". However, as I mentioned before whenever I run the form alter on either of those fieldgroup fieldsets they don't print in the form at all, this is the bug I think? Anyway, hope the image helps clarify what I am doing in case its not clear.

Stalski’s picture

Yeah, i know what the problem is. I will send you the solution in a minute. #fieldgroups contains the group object, not the form element.

Stalski’s picture

For module named custom:

/**
 * Implements hook_field_group_build_pre_render_alter().
 * @param Array $elements by address.
 */
function custom_field_group_build_pre_render_alter(& $element) {
  //dsm($element);
  // Alter the element like $element += array(yourstates)
}

You will find the elements in the array there.

So you were doing nothing wrong, just the wrong hook. As fieldgroup can only work after the alter, it provides its own hooks to alter things.
You will need to flush cache and debugging like with dsm will only appear the second page load.

Stalski’s picture

Status: Active » Needs review

Can you close this if the problem is solved.

Jeff Burnz’s picture

Status: Needs review » Active

OK I am using the new hook and tried with the following code but the assignment operator gives me a fatal error (Fatal error: Unsupported operand types), which I assume is because something in the array is bad, but I don't understand this well enough to figure it out.

  $element['#fieldgroups']['group_gastroscopy'] += array(
    '#states' => array(
      'visible' => array(
        '#edit-field-procedure-und' => array('value' => 'gastroscopy'),
      ),
    ),
  );

If I just use a strait = it does get added (the #states) but of course it all fails because everything else gets wiped out, oddly though the fieldset keeps printing as they seem to be in two places - both in #groups and #fieldgroups

I also get this notice:

Notice: Object of class stdClass could not be converted to int in antonelli_field_group_build_pre_render_alter() (line 41 of template.php).

Line 41 is: $element['#fieldgroups']['group_gastroscopy']

Stalski’s picture

Ok i will give you working code. #fieldgroups is not an element! Elements in drupal are never with # , that are properties.

Stalski’s picture

Status: Active » Needs review

Sorry had a computer crash and appearently forgot about this one not being posted.
Here is what i came up that works for a group called group_content in a vertical tab or horizontal tab.

/**
 * Implements hook_field_group_build_pre_render_alter().
 * @param Array $elements by address.
 */
function custom_field_group_build_pre_render_alter(& $element) {

  if (!isset($element['#view_mode'])) {
    $element['group_content'] += array(
      '#states' => array(
        'visible' => array(
          '#edit-menu-enabled' => array('checked' => TRUE),
        ),
      ),
    );
  }

}
Jeff Burnz’s picture

I'm really sorry but I still get the unsupported operand error for the assignment operator.

This is the code I used, based on the above, my module is called "appx", I have a fieldset called 'group_colonoscopy' which is inside a tab (I've switched to horizontal tabs now as this makes more sense for the layout of the form).

function appx_field_group_build_pre_render_alter(& $element) {

  if (!isset($element['#view_mode'])) {
    $element['group_colonoscopy'] += array(
      '#states' => array(
        'visible' => array(
          '#edit-field-procedure-und' => array('value' => 'colonoscopy'),
        ),
      ),
    );
  }

}
Stalski’s picture

And you are really sure that "$element['group_colonoscopy']" exists??
What does dsm tell you on the $element or $element['group_colonoscopy'] ? That is the devel tool to log messages to the screen. When doing things like that, you must use it, there is no other way (that is better).

I think you just tried that without checking if it exists, no? As i said before, you can try

$element['group_colonoscopy']['#states']

but in this case, i am pretty sure the element is not there. It will be nested somewhere deeper. In your case, it will be a little trial and error.

Jeff Burnz’s picture

OK, part of my problem is that what Devel is showing me in Krumo is not accurate to the structure of the form, instead I just went off the manage fields display and guessed the structure, so I now have the states being added in the right place etc.

However I now have an issue with the JS settings not being added correctly - the normal fieldset ID's are not printing and not being added to the JS settings, such as...

This...

"#":{"visible":{"#edit-field-procedure-und":{"value":"colonoscopy"}}}

...should be this...

"#edit-group-colonoscopy":{"visible":{"#edit-field-procedure-und":{"value":"colonoscopy"}}}

Even hacking the ID attribute into field_group_field_group_pre_render() such as this did not work...

'#attributes' => array('class' => explode(' ', $classes), 'id' => 'edit-' . drupal_html_class($group->group_name)),

Now, it does work with fields within the fieldset, so this is what I will do if we can't solve this last issue, I'll pull the fields out of the fieldset and delete that group, which is not ideal but at least I now have a way of making this work!

Thanks so much for your patience and code snippets, really appreciate all of it :)

Stalski’s picture

Status: Needs review » Closed (fixed)

Yeah, i had that error too since it was a quick preview.

  if (!isset($element['#view_mode']) && isset($element['group_content'])) {
    $element['group_content']['#states'] = array(
      'visible' => array('#edit-menu-enabled' => array('checked' => TRUE))
    );
  }

I think you best add a few checks more ;), like isset($element['group_content'])

rv0’s picture

Status: Closed (fixed) » Active

Does not seem to work with horizontal tabs nested in vertical tabs

dpm($element) in hook_field_group_build_pre_render_alter never shows the horizontal tabs.
changed execution order in hook_module_implements_alter but did not work either.

is there some other mechanism required for horizontal tabs?

griz’s picture

I think this whole thread is very anal.

Jeff Burnz’s picture

For those not aware I believe griz is making a joke here, due to the subject nature of the site I was working on... for recording endoscopic records...

Martijn Houtman’s picture

Thanks, I was looking for this hook!

clairedesbois@gmail.com’s picture

Issue summary: View changes

Hello,

The #id have been removed. If you want use #states on your field group, you must add it:

function my_module_field_group_build_pre_render_alter(&$element) {
if (isset($element['my_group'])) {

    $element['my_group'] += array(
      '#states' => array(
        'visible' => array(
          'input[name="show_my_group"]' => array('checked' => TRUE),
        ),
      ),
      '#id' => 'my_group',

    );
  }
}
WorldFallz’s picture

Just a confirmation.... #20 works for me.

anou’s picture

Thanks to Calystod! That's the issue solution.

jimmyko’s picture

#20 cannot work for me. I am using field_group-7.x-1.5

Anyone has idea?

===

update:

pre_render did the trick. But please note that dpm() is not working in the pre_render hook. You have to use kpr() or var_dump() for your debug purpose.

wildfeed’s picture

kpr($element['my_group'])

helped me find out the value for

'#id' => 'my_group',

In my case it was

'#id' => 'edit-profile-main',

that turned the trick.

mibfire’s picture

I have a radio box and i would like to hide a group(section) but this doesnt work. Here is my code:

function MYMODULE_field_group_build_pre_render_alter(&$element) {
  if (isset($element['group_personal_details'])) {
    $element['group_personal_details']['#id'] = 'group-personal-details';
    $element['group_personal_details']['#states'] = array(
      'invisible' => array(
        ':input[name^="field_i_wish_to_remain_anonymous"]' => array('value' => '1'),
      ),
    );
  }
}

I added id to group, field_group is 1.5. There is no php or js error.

The solution:

I had to set id into field group settings in UI and add wrapper around the group because state.js finds a wrapper(.form-item or .form-submit or .form-wrapper) to hide. Take a look at code snippet from state.js:

$(document).bind('state:visible', function(e) {
  if (e.trigger) {
      $(e.target).closest('.form-item, .form-submit, .form-wrapper').toggle(e.value);
  }
});

And the php code is:

function MYMODULE_field_group_build_pre_render_alter(&$element) {
  if (isset($element['group_personal_details'])) {
    $element['group_personal_details']['#states'] = array(
      'invisible' => array(
        ':input[name^="field_i_wish_to_remain_anonymous"]' => array('value' => '1'),
      ),
    );
    $element['group_personal_details_wrapper'] = array(
      '#type' => 'container',
      '#attributes' => array(
        'class' => array(
          'form-wrapper',
        ),
      ),
    );
    $element['group_personal_details_wrapper']['group_personal_details'] = $element['group_personal_details'];
    unset($element['group_personal_details']);
  }
}
joewhitsitt’s picture

I am unable to get #states to work with my nested field_group. #20 works for "top-level" fieldsets.

My structure is such:

- group_my_vtab (vertical tab)
  - group_my_fieldset (fieldset)

The structure $element['group_my_vtab']['group_my_fieldset'] doesn't exist. Instead the structure of $element['group_my_vtab'] is this:

group_my_vtab (Array, 2 elements)
  #weight (String, 1 characters ) 1
  #group (Object) stdClass
    id (String, 1 characters ) 5
    identifier (String, 40 characters ) group_my_vtab|node|my_content_type|form
    group_name (String, 18 characters ) group_my_vtab
    entity_type (String, 4 characters ) node
    bundle (String, 11 characters ) my_content_type
    mode (String, 4 characters ) form
    parent_name (String, 0 characters )
    table (String, 11 characters ) field_group
    type (String, 10 characters ) Overridden
    export_type (Integer) 3
    disabled (Boolean) FALSE
    export_module (String, 17 characters ) my_module
    label (String, 12 characters ) my_vtab
    weight (String, 1 characters ) 1
    children (Array, 6 elements)
      0 (String, 14 characters ) field_keywords
      1 (String, 15 characters ) group_my_fieldset
format_type (String, 3 characters ) tab
format_settings (Array, 2 elements)
  formatter (String, 6 characters ) closed
  instance_settings (Array, 3 elements)
    description (String, 0 characters )
    classes (String, 35 characters ) group-my_vtab field-group-tab
    required_fields (Integer) 1
  collapsible (Boolean) TRUE
  collapsed (Boolean) TRUE
  classes (String, 73 characters ) collapsible collapsed required-fields group-or...
  description (String, 0 characters )

I can't get to the group_my_fieldset object within hook_field_group_build_pre_render_alter() unless i target $element['#groups'] or $element['#fieldgroups']. I tried these as well, but wasn't successful.

miiimooo’s picture

Version: 7.x-1.x-dev » 8.x-1.x-dev

Solution in #25 worked for me too (in D8). Thanks @mibfire

I did this (which is identical with #25 for two small changes/additions (note this is a fieldgroup inside another fieldgroup)


function MYMODULE_field_group_build_pre_render_alter(&$element) {
  if (isset($element['group_membership']['group_membership_data'])) {
    $element['group_membership']['group_membership_data_wrapper'] = array(
      '#type' => 'container',
      '#attributes' => array(
        'class' => array(
          'js-form-item',
        ),
      ),
      '#weight' => $element['group_membership']['group_membership_data']['#weight'],
    );
    $element['group_membership']['group_membership_data']['#states'] = array(
      '!visible' => array(
        '[name="field_membership"]' => array('value' => '_none'),
      ),
    );
    $element['group_membership']['group_membership_data_wrapper']['group_membership_data'] =
      $element['group_membership']['group_membership_data'];
    unset($element['group_membership']['group_membership_data']);
  }
}

  • Stalski committed 94eaf4a on 8.x-3.x
    #1053174 by Jeff Burnz: hook_form_alter form state problems.
    
    
handkerchief’s picture

handkerchief’s picture

How is it going on? Is the workaround with the custom wrapper in MYMODULE_field_group_build_pre_render_alter() the final solution?

eric.chenchao’s picture

Status: Active » Needs review
FileSize
2.47 KB

For Drupal 8, 'js-form-wrapper' class is required for Form states.js. If we could add this class into the form HTML, that avoids to using an extra wrapper.

/**
 * Implements hook_field_group_build_pre_render_alter().
 */
function MYMODULE_field_group_build_pre_render_alter(&$element) {
  $form_id = $element['#form_id'];
  if ($form_id == 'my_example_form' && isset($element['group_example'])) {
    // Add form states to the field group.
    $element[$key]['#attributes']['class'][] = 'form-wrapper';
    $element[$key]['#attributes']['class'][] = 'js-form-wrapper';
    $element['group_example']['#states'] = [
      'visible' => [
        ':input[name="field_are_you_ok"]' => ['value' => 'yes'],
      ],
    ];
  }
}

Or we could apply the patch attached to add those HTML class to the template and the code will be:

/**
 * Implements hook_field_group_build_pre_render_alter().
 */
function MYMODULE_field_group_build_pre_render_alter(&$element) {
  $form_id = $element['#form_id'];
  if ($form_id == 'my_example_form' && isset($element['group_example'])) {
    // Add form states to the field group.
    $element['group_example']['#states'] = [
      'visible' => [
        ':input[name="field_are_you_ok"]' => ['value' => 'yes'],
      ],
    ];
  }
}

The patch should work in the both 8.x-1.x and 8.x-3.x branches.

handkerchief’s picture

@eric.chenchao it works like a charm! So it would be great the patch would now be added to the module.

GaëlG’s picture

Status: Needs review » Reviewed & tested by the community

Patch #31 works. Thanks! :)

jimmyko’s picture

Will the fix back port to 7.x module?

DuneBL’s picture

I don't know why, but MYMODULE_field_group_build_pre_render_alter is not called...
I have tried also with MYTHEME_field_group_build_pre_render_alter without success.
I have even added a dpm and a drupal_set_message in the module itself: field_group_field_group_build_pre_render_alter

function field_group_field_group_build_pre_render_alter(& $element) {
    drupal_set_message("rrr"); //NOTHING IS DISPLAYED
   ...

...without luck!!!
I have tested with fieldset, detail, acordion,... all the possibilities

Drupal 8.5
field_group 8.x-3.x
The fieldset is in a contact form.

Any hint/help?

DuneBL’s picture

regarding #35, I could hide/unhide a fieldset (based on the value of a select list) by replacing the fieldset group made in the UI by a fieldset group created in form alter.
I had to move the 2 fields (created in the UI) that have to be in the fieldset inside this newly created fieldset

// Add fieldset programmatically to allow '#states' to work
    $form['my_fieldset'] = [
        '#type' => 'fieldset',
        '#title' => t('Title of the fieldset'),
        '#states' => [
            'visible' => [
                'select[id="my-select-list-id"]' => [
                    'value' => 'show_fieldset'
                ]
            ]
        ]
    ];
    // Move fields in the fieldset
    $form['my_fieldset']['my_field_1'] = $form['my_field_1'];
    $form['my_fieldset']['my_field_2'] = $form['my_field_2'];
    // unset the moved fields
    unset($form['my_field_1']);
    unset($form['my_field_2']);

...This is working without patch...
Conclusion:
- '#STATES' with fieldset created in UI =>I assume you should use #31
- '#STATES' with fieldset created in FORM_alter =>Works as expected

In all cases, as stated in #35, MYMODULE_field_group_build_pre_render_alter is never called

nathandentzau’s picture

I used hook_field_group_form_process_build_alter() to get #31 to work.

larowlan’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +australia-nz-friday-triage
  1. +++ b/templates/field-group-accordion-item.html.twig
    @@ -15,25 +15,23 @@
    -
    ...
    -
    ...
    -
    
    +++ b/templates/field-group-accordion.html.twig
    @@ -15,7 +15,8 @@
    -
    -<div {{ attributes.addClass(classes) }}>{{ children }}</div>
    +<div{{ attributes.addClass(classes) }}>{{ children }}</div>
    

    out of scope changes?

  2. +++ b/templates/field-group-accordion-item.html.twig
    @@ -15,25 +15,23 @@
    \ No newline at end of file
    

    whitespace issue here.

  3. +++ b/templates/field-group-html-element.html.twig
    @@ -27,4 +32,4 @@
    -</{{ wrapper_element }}>
    \ No newline at end of file
    +</{{ wrapper_element }}>
    

    whitespace issues

sagesolutions’s picture

In all cases, as stated in #35, MYMODULE_field_group_build_pre_render_alter is never called

I also have the same issue. I created a module and implemented the hook_field_group_build_pre_render_alter() function, but it was never called.

FatherShawn’s picture

Here's a re-roll of #31 against 3.0-RC1 release.

Anybody’s picture

Version: 8.x-1.x-dev » 8.x-3.x-dev

Changing the branch to the future one.

texas-bronius’s picture

Rerolled #40 patch and states works for me to be able to do the hooks like in #31, thank y'all!
Note that #31 is about field_group on display, whereas I needed it on form alter using hook_field_group_form_process_build_alter() which works.

swentel’s picture

Status: Needs work » Needs review
FileSize
1.76 KB

re-uploading patch for the bot

swentel’s picture

Status: Needs review » Closed (works as designed)

Hmm, I'm a bit on the fence here to add those classes in the default templates as they are not needed by default. The HTML element suddenly looks well, a bit silly. Since they are templates, you can also just override the template if you really need them.

This issue is also extremely old, so closing.

guistoll’s picture

Here's how I'm adding #states on a field group:

I have a checkbox called field_custom_content and a group called group_custom_content. The group will only be displayed when field_custom_content checkbox is true/checked.

These fields are in a paragraph inside a content type.

/**
 * Implements hook_field_group_build_pre_render_alter().
 */
function MYMODULE_field_group_form_process_build_alter(&$element) {
  if (isset($element['group_custom_content'])) {
    $element['group_custom_content']['#states'] = [
      'visible' => [
        ':input[name="field_paragraphs[0][subform][field_custom_content][value]"]' => [
          'checked' => true
        ]
      ]
    ];
  }
}
SKAUGHT’s picture

field_group.api.php --> hook_field_group_form_process() worked for me

D8 field group 3.1

/**
 * Implements hook_field_group_form_process().
 */

function MYMODULE_field_group_form_process(array &$element, &$group, &$complete_form) {
 if ($element['#parents'][0]=='group_user_action') {
  // Add form states to the field group.
    $element['#states'] = [
      'visible' => [
        'select[name="field_display_mode"]' => ['value' => 'modal'],
      ],
    ];

  }
}
wstocker’s picture

Patch #43 is failing with the composer update to drupal/field_group (3.2.0)
on diff --git a/templates/horizontal-tabs.html.twig b/templates/horizontal-tabs.html.twig

ElusiveMind’s picture

Updated patch file to work with field_group 3.2.0

lind101’s picture

For those landing here looking for a way to add #states to field_groups in a more generic way via traditional form_alter_hooks, the below helper hook works well.

/**
 * Implements hook_field_group_form_process().
 */
function my_module_field_group_form_process(array &$element, &$group, &$complete_form) {
  /**
   * Provides a generic way for assigning Form API #states to field group elements
   *
   * @usage - In a from_alter hook the Group object can be modified to include a form_api_states property,
   *          which is picked up here and applied to the field group element
   * @code
   *  $form['#fieldgroups']['group_my_group']->form_api_states = [
   *     'visible' => [
   *        ':input[name^="my_field_name"]' => ['checked' => TRUE],
   *      ]
   *    ];
   * @endcode
   */
  if (isset($group->form_api_states) && is_array($group->form_api_states) && !isset($element['#states'])) {
    $element['#states'] = $group->form_api_states;
  }
}
dmezquia’s picture

The hook hook_field_group_form_process works ok for me too.