Hi,
Problem/Motivation
Faced with issue that when add conditional fields dependency to hide/show fields inside the group, group is always visible.
Would be great to have a feature that hide group when all fields inside of it are hidden.
Steps to reproduce
- Create a content type that contains the text fields
field_test_trigger, field_hidden_by_trigger
- Add a field group to the form and move
field_hidden_by_trigger to be a group child
- Add a
hook_form_FORM_ID_alter to apply javascript states to hide field_hidden_by_trigger when field_test_trigger is not empty (see example code below)
- Go to the form and enter a value into
field_test_trigger
- The field group is still visible even though
field_hidden_by_trigger is now hidden. The field group should also be hidden unless the Display element also when empty setting is enabled.
/**
* Implements hook_form_FORM_ID_alter().
*/
function my_module_form_node_test_content_form_alter(&$form, FormStateInterface $form_state): void {
$form['field_hidden_by_trigger']['#states'] = [
'visible' => [
':input[name="field_test_trigger[0][value]"]' => ['value' => ''],
],
];
}
Proposed resolution
- Add a
field_group.js Javascript state:visible event listener
- This listener will call a new
Drupal.FieldGroup.setParentFieldGroupVisibility method and pass in the element from the state:visible event (i.e. the element being hidden or shown)
Drupal.FieldGroup.setParentFieldGroupVisibility will check if the element is a field group child and if it is, find the element's parent field group and pass that into a new Drupal.FieldGroup.setFieldGroupVisibility method. It will also call itself passing in the group, to handle the hiding/showing of nested groups.
Drupal.FieldGroup.setFieldGroupVisibility will check if the current field group is empty by calling a new Drupal.FieldGroup.isGroupEmpty method. Depending on if the group is empty or not, a new field_group:group_empty or field_group:group_not_empty event will be triggered.
field_group:group_empty and field_group:group_not_empty event listeners are added to specific group type js files to handle hiding and showing the group element/s
Comments
Comment #2
mariiadeny commentedComment #3
mariiadeny commentedComment #4
mariiadeny commentedFix naming
Comment #6
andypostany reason to duplicate?
Comment #7
savkaviktor16@gmail.com commentedRe-rolled
Comment #8
tessa bakkerDoesn't work with horizontal tabs, all tabs are hidden.
Tested with the latest dev version (072bf212d8e13aa242a4e274e5a4837a0e0ffc5e)
Comment #9
piggito commentedFixed the issue about all tabs hiding + I also noticed that on Accordion Items the Field Group title wasn't hiding. Including both changes in the attached patch.
Comment #10
publishing future commentedI applied the patch in #9 to Field Group 8.x-3.x-dev (i.e. 8.x-3.0-beta1+21-dev) but nevertheless groups that only include fields which are hidden by conditional fields dependency are still visible. The field groups are of type "Details".
Comment #11
publishing future commentedPatch in #9 seems to work onlywith field groups of type html. However, if I set the _first_ field group to "html", the following field groups with hidden fields of type "details" are hidden as well.
Comment #12
publishing future commentedWhereas the patch #9 solves the problem for fields hidden by "conditional fields" module, the problem still persists for fields hidden by "field states ui" module.
Comment #13
andypostYep, it needs own classes which both modules could use
Comment #14
w01f commentedThanks for everyone's time with this!
I applied the patch and it works great for initial page load, but if I apply the correct condition for the fields to become visible, and then undo the condition (in my case unchecking a boolean field) - the fields once again disappear but the empty fieldset group is still shown.
Comment #15
andypostComment #16
larowlanIs this still an issue after #2986455: Empty fieldgroups are showing in forms
Comment #17
inversed commentedI believe this is still occurring, specifically, for Tabs (as mentioned in the referenced issue in #16). That's the behavior that I've experienced. When Conditional Fields makes a field "invisible" and that field is the only field in a tab, that tab will still be shown.
If a Tab has no fields in it (i.e. removed using the form display manager), then the tab will not be shown. That is the bug that was fixed successfully in Issue #2986455.
Comment #18
liquidcms commentedeven without Conditional Fields, with the patch in #9 as well as the patch from #2986455: Empty fieldgroups are showing in forms, i still get empty sidebar details tab showing: https://www.screencast.com/t/JR4Tyo8W
Comment #19
liquidcms commentedI changed FG type to simple fieldset instead of details sidebar.. and this still doesn't work. https://www.screencast.com/t/eg5UXCqAp
Comment #20
vinothkannan commentedAny luck on Drupal 8.8.4?
Comment #21
miedward commentedUpdated patch in #9 to work with Drupal 8.8.6 and a refactor of some code into FormatterHelper.php
Comment #22
miedward commentedProbably doesn't fix the use case the #9 patch didn't but fixes the issues I have on my site.
Comment #23
rp7 commentedI can't seem to apply the patch in #21.
I'm having this issue on a multilingual site. I have a content type of which some fields are not translatable. These fields are only visible on the original translation (this is how Drupal core works). For my use case, these untranslatable fields all happen to be in the same field group. When translating a node of this particular content type, the field group still renders although it being empty.
The function responsible for setting the form elements #access key for untranslatable fields to FALSE is located at ContentTranslationHandler::entityFormSharedElements() provided by content_translation module. This is run via a #process callback.
The function responsible for tracking down and removing empty fields group is called field_group_remove_empty_form_groups(). This is also run via a #process callback.
The issue is that the field_group #process callback runs before the content_translation #process callback.
The patches proposed earlier are trying to hide empty field groups through JavaScript. Taking the above into account, I believe running field_group_remove_empty_form_groups() as late as possible (eg. in an #after_build callback) gives you the best chance of having empty field groups correctly being removed. The patch attached implements this.
I can confirm that this fixes the content_translation issue.
As for the Conditional Field module: I'm not using it, so I can't validate if this patch also fixes that issue. If not: the issue is probably of the same nature (Conditional Field doing its thing after field_group_remove_empty_form_groups() has already run).
Comment #24
spadxiii commentedThe patch in #23 works good, but not perfect. I think it's also way better than hiding using javascript.
The process method is replaced by an after-build: field_group_form_process_after_build . The doc-block needs a little more update: an after-build has a return-value :)
What does not work is nested groups that are empty: these still force the parent group to be visible, because their access is never set to false. I think this is because the after-build is only run once for the whole form. Perhaps this after-build needs to be recursive? (and do a depth-first check: the deepest child first, then bubble back up).
Comment #25
prudloff commented#23 does not work for our use case, because we are using states to hide the field, so it has to be in JS.
#21 does not work for nested field groups, because they don't have the
field-groupclass (it is overridden byfield-group-child-field). The attached patch fixes that.Comment #26
tim-dielsDoes not apply anymore.
We should keep the original thinking method here. As you can see, they add the class array. Default there are is no class array. So checking would be better and then merge or add.
Comment #27
james.williams#25 makes a good point that groups may be hidden in javascript, which would require a javascript-only solution.
For the server-side solution, to solve groups hidden on the server-side (most commonly by content translation), #3069365: Emptiness check in field_group_remove_empty_form_groups() does not account for empty containers contains something that looks good to me.
I suggest this issue focuses on hiding groups when they are hidden by javascript, if that's needed.
Comment #28
james.williamsSorry, I'd misinterpreted that other issue, although it is indeed a server-side change. #3127179: Empty group due to hiding fields on translation form are not hided now has a patch for the server-side issue, and matches #23's report of content_translation causing the issue.
Comment #29
duneblI think that #25/#26 are targeting only accordions.
I tested it without luck on a
detailsgroup rendered by the default olivero theme.Here is the rendered html of my "not hided" group
As you can see, there isn't any
.accordion-itemclassNote: The field (in the group) has been hidden by setting the '#access' key to FALSE in the regular
form_alterComment #30
heikkiy commentedTested the patch with 3.2 and it doesn't seem to work with tabs.
I have one field group marked as a tab and adding the condition to it, hides the fields inside it but it doesn't hide the actual tab.
I checked that there is no change in the HTML code.
Looking at the patch, it seems like its only triggering for elements with the class .accordion-item where as the tabs have the following HTML structure:
<li class="horizontal-tab-button horizontal-tab-button-1 last selected" tabindex="-1" data-horizontaltabbutton="1"><a href="#edit-group-researcher-profile"><strong>Researcher profile</strong><span class="summary"></span><span id="active-horizontal-tab" class="visually-hidden">(active tab)</span></a></li>Comment #31
dtamajon commentedI confirm the patch is not working with horizontal neither vertical tabs.
This is the JS version for tabs working, but we should find the way to work with all group elements.
Comment #32
kay_v commentedhousekeeping....
I'm changing status to 'needs work' based on comments posted over the course of the last year; I'm guessing it was meant to be changed earlier
Comment #33
tame4tex commentedMy attempt to get it working for all field group formatters, inspired by previous patches.
I went a slightly different route and provided a field group js function to hide a field group and its tab (if applicable). Then each formatter is required to call the function during its process or attach function and provide the function parameters as needed. The formatter is also required to bind to the `states:visible` event.
Preliminary manual testing has been done on tabs, accordion items, fieldsets and details.
This really needs tests written, which is beyond my current scope.
Comment #34
tame4tex commentedComment #35
tim-dielsThanks for the work, this did the trick for me and looks good. I added this also to the HTML element.
Comment #36
tim-dielsApologies for the error in code. Fixed in new patch.
Comment #38
joshhytr commentedRe-rolled patch 36 for module tag
8.x-3.4and added semi-colons at the end ofletvariable declarations.I am providing an updated patch and have also pushed to the issue fork.
Comment #40
sokru commentedThis should resolve the Drupal 10 issues.
Comment #41
duneblThis patch is nice and working well except if we are adding fields in an empty group in the hook
form_alter.I am using the following function to add $form[$field_name] to a group (id=$group_name):
If I add $form['field_to_add'] in a group which is empty but which have the option "
Display element also when empty" checked; then the group is not displayed.To summarize, there are 2 issues:
1-The patch doesn't take into account the option
Display element also when empty2-The patch doesn't take into account any element added to the group in the
form_alterhookComment #42
prudloff commentedThe patch works correcly on initial load, but it does not seems to work correctly when detecting a change.
We have a fieldset containing 3 fields that can be shown/hidden depending on when another checkbox field is checked (we use conditional_fields for this).
The field group is initially hidden but if I make the fields visible then hide them, the field group is not hidden and is displayed empty.
This seems to happen because when
Drupal.FieldGroup.hideGroupIfEmpty()evaluate thedisplayproperty of the fields, the last does not havenoneyet. So it might be some kind of race condition that makes it check the field too soon.If I do something like this, then it works correctly:
(This is obviously not the way to the fix the problem, but it helps demonstrate it.)
Comment #43
vensiresComment #44
mιχaliς commentedPatch failed on field_group 3.6 and Drupal 10.3
Comment #45
karen-kramek commentedHello everyone,
Re-holl of patch field_group-2978747-40.patch (8.x-3.0), now covering the module version 8.x-3.6.
Comment #46
a.milkovskyComment #47
pakmanlhUnfortunately I can confirm the behavior described by #42 working only initially.
Comment #48
vensiresComment #49
tgaugesWould
MutationObserverbe an acceptable solution for #42? One would need to observesubtree,childList, andattributes.I will create a new branch in the issue fork based on
2978747-hide-group-if.Comment #50
tgaugesYou can take a look at https://git.drupalcode.org/issue/field_group-2978747/-/tree/2978747-hide-group-with-mutation-observer for my solution for #42.
There don't seem to be any tests implemented for this issue?
Comment #51
tame4tex commentedUpdating to new major version.
Comment #55
tame4tex commentedNot only is there an issue with the code only working initially, I also experienced issues with it not working with nested groups. To fix these issues I implemented a different approach.
We need to ensure that when the
state:visibleevent is fired we not only set the visibility of the closest field group but we continue up the DOM to set the visibility of parent field groups. This is easier to handle with onestate:visibleevent listener in thefield_group.jsthan one for each field group type.Because each field group type might need to do different things when its children are all hidden vs when a child is visible, once we have determined the current visibility of the field group children we need to hand off what is done to the field group to the js file for the different types.
I have updated the Issue Summary with my proposed resolution. Given the significant changes to the previous version and the merge conflict issues in updating the old solution branches, I have added a new 2978747-hide-group-4.x and opened a MR.
I have also added preliminary testing for this bug.
@tgauges: Interesting concept with the MutationObserver, although I am wondering if it is more than what is needed in this instance? Given the new approach, what does it do better?
Comment #56
pakmanlhI can confirm the last / new approach from 2978747-hide-group-4.x works fine. thank you!
Comment #57
tgauges@tame4tex MutationObserver is a catch-all solution which also can work if the DOM is mutated by something other than the Drupal Form API
#statesproperty.In my opinion you are correct: It is probably more than what is needed. I think it's enough to react to changes caused by the
#statesproperty.Comment #58
tame4tex commentedI have pushed a couple of fixes to the MR due to issues encountered.
`Display element also when empty` setting was not being respected. I have now added a test for this and fixed the bug by adding a css class
if this setting is enabled and then checking for that class in the logic.
I also encountered a weird bug in Safari 18.x where it was ignoring the style attribute on the element being hidden/shown by states and instead determining the display value to be "none" when it was actually "block". I have adjusted the code to specifically check the style attribute on the element first and only get the computed style if the style attribute display value is empty.
I have switched the status back to Needs Review due to these changes.
Comment #59
imclean commentedShould this work with forms loaded via ajax? I've applied the patch to the 4.0.x branch but it hasn't made any difference.
In my case, the target fieldset and controlling fields are within a paragraph type. When adding a new paragraph the fields are correctly shown or hidden while the fieldset wrapper is always visible.
Comment #60
imclean commentedIgnore the above, I'm having patching issues.
Comment #62
pcambraAdding a patch file with the rebase above for 4.0.0
Comment #63
carma03 commentedConfirming patch on #62 comment worked good. Tested on
D11.2.8andPHP 8.3.Bear in mind that the option Display element also when empty should be disabled into the Group Tab for get it to work properly:
Thanks!
Comment #64
er.garg.karanI am using Drupal 11.2.10 and field group 4.0.0.
I have a field group inside a paragraph. There are a few fields under that field group and I am using
#statesto show/hide those fields on the change of value of another select field.When a value in the select field hides these fields, it works fine and the field group also hides as there is no other field to show in the field group. But as soon I make a selection in the select field that has to show the fields under the field group, the fields show but there is no field group as it never existed.