Split from #2177469: Move node base widgets to the top level of the form

Currently, an $element that wants use the #group feature needs to make sure 'form_process_group' & 'form_pre_render_group' run as part of its processing & rendering.

So far, only 'container' types specify those in their hook_element_info() definition : fieldset, details, container
Patch linked above adds it to: datetime, textfield, textarea, checkbox as well, which sounds a bit arbitrary, and not too scalable.

Ideally #group should "just work" on any element type, not just on the ones that provision for it.
form_process_group() & form_pre_render_group() should just run on every sub-element in a form / render array as part of the default process / render stack.
No biggie for form_pre_render_group(), it's an early opt-out if $element['#group'] is not set. form_process_group() might need some refactoring to avoid a perf hit.

Problem / current behavior:

Drupal FAPI doesn't support visually grouping fields without affecting the field / form data structure as it requires nesting the fields, which is then reflected in the data structure:

    $form['contact'] = [
      '#type' => 'details',
      '#title' => t('Contact details'),
      '#open' => TRUE,
    ];    

    $form['contact']['name'] = [
      '#title' => $this->t('Name'),
      '#description' => $this->t('Enter your name.'),
      '#type' => 'textfield',
      '#default_value' => $this->options['name'],
    ];

Proposed solution:

Additonally, allow to group FAPI elements only visually, without affecting the field / form data structure. So that both ways are supported:

    $form['contact'] = [
      '#type' => 'details',
      '#title' => t('Contact details'),
      '#open' => TRUE,
    ];    

    $form['name'] = [
      '#title' => $this->t('Name'),
      '#description' => $this->t('Enter your name.'),
      '#type' => 'textfield',
      '#group' => 'contact',
      '#default_value' => $this->options['name'],
    ];

TODO:

  1. Implement and write tests
  2. Update documentation from https://www.drupal.org/node/262758 (Drupal 6) for Drupal 8+

Issue fork drupal-2190333

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Pancho’s picture

Important, currently incomplete feature that allows decoupling visual form output from form value structure.

@tstoeckler in #2177469-45: Move node base widgets to the top level of the form:

There are different use-cases here that need to be consider. If I just want to change the #default_value or the #description of a form element this patch makes that easier because I can just blindly to that in $form[$field_name]['#foo'] and don't need to bother with possible nesting.

Another use-case, however, is changing the *output* structure of the form, i.e. moving form elements into different groups, adding form elements into existing groups, perhaps nesting groups into each other, etc. With fieldgroup.module in conrib this is currently a non-trivial task that requires deep knowledge about the different structures and array keys that fieldgroup module uses. It's not as easy as simply setting/altering $form[$field_name]['#group'] or anything similar.

@sun in #1856178-1: '#group' Form API property only works with <details> elements:

We should turn the #group facility into a ultra-generic thing.

Currently, the feature is incomplete and inconsistent. There's no reason why '#group' works with textfields and a single checkbox, but not with selects or multiple checkboxes.

@sun in #2177469-41: Move node base widgets to the top level of the form:

It would be a very good idea to start an effort to convert all forms throughout core to the new concept, so as to ensure and guarantee a good and consistent DX. [...] The form_process_group() and form_pre_render_group() callbacks should be removed and the concept should be refactored directly into FormBuilder.

We may refactor the logic directly into FormBuilder, deprecating the existing callbacks. But as a first step, let's add the callbacks to all elements in ElementInfoManager, then let's see which elements need special consideration (VerticalTabs for sure, but also Container after #2893586: Add #optional support to the Container render element.

Here's a first patch. Let's see how it tests.

Status: Needs review » Needs work

The last submitted patch, 7: element_group_feature_2190333-7.patch, failed testing. View results

Pancho’s picture

Version: 8.6.x-dev » 8.8.x-dev
Status: Needs work » Needs review
FileSize
9.77 KB
2.76 KB

Not too bad.

Fixing the test failure.

Now we may also simplify FieldLayoutBuilder::buildForm() a bit, removing the #group processing code added in #2796173-39: Add experimental Field Layout module to allow entity view/form modes to switch between layouts.

This patch landing should also be unblocking #2846393: [PP-1] Investigate alternative approaches to moving fields in FieldLayoutBuilder::buildView().

Furthermore, we may refactor many forms, as far as there are no BC concerns, replacing the value-reparenting with '#parents' by form-reparenting using '#group'. This may be a followup or rolled in. If we opted for rolling it in, we'd immediately get more test coverage for '#group'.

Status: Needs review » Needs work

The last submitted patch, 9: element_group_feature_2190333-9.patch, failed testing. View results

Pancho’s picture

Okay, let's rewind and leave layout builder alone for now.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

paper boy’s picture

Patch is working well on a rather complex D 8.7.8 project.
Thanks a lot!

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

kawaljeet singh’s picture

Not working with Ajax callback, if we Replace select options using ajax callback.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Grimreaper’s picture

ranjith_kumar_k_u’s picture

Status: Needs review » Needs work

The last submitted patch, 20: 2190333-20.patch, failed testing. View results

Anybody’s picture

Issue summary: View changes
Issue tags: +Needs documentation

Just ran into the same issue. The key point is, that quite often a way is required to group fields (and groups) without changing the field / form data structure.

While the nesting functionality works great, when you have full control over the code or even want nesting, everything is all right. But if form values are stored by a third party module or core, you may simply change the display, but not the data structure.

#group seems to be a good approach for that case, where you don't want to change the nesting structure.

Adding the "Needs documentation" tag, once this is available. Currently this only seems to be documented on the Drupal 6 documentation page: https://www.drupal.org/node/262758

I only found this blog article about using #group for this, while the documentation page only shows nesting examples. #tree doesn't seem to be helpful to prevent

Example case: Extend views StylePluginBase and add further fields. Use "details" field group to structure the additional settings, without breaking the form save logic. => Impossible (without manually massaging the nested values).

I wrote a blog post about that with examples: https://julian.pustkuchen.com/en/drupal-9-form-api-grouping-without-affe...

As this isn't really documented, what's the expected behavior and what's the plan for that in core?

Anybody’s picture

Issue summary: View changes
Anybody’s picture

Issue summary: View changes
Anybody’s picture

Issue summary: View changes

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

jayhuskins’s picture

The SystemMenuBlock gets around this issue with a #process value on the container elements that calls processMenuLevelParents to remove the container from the form values.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Carlitus’s picture

Tested and for the moment it works well.

Without a Checkbox, for example, works well with a details parent but not a Radios with a details parent.

With the #20 patch it works well with the Radios child.

I think getting this is a big step for Drupal, since as @Anybody says many times you can't modify the form structure but you do need to be able to group it.

Needed to make this patch: https://www.drupal.org/project/style_options/issues/3310055#comment-1519...

Anybody’s picture

@Grimreaper and @Pancho any ideas how we can take this issue forward and perhaps get some frontend framework manager feedback on this?

I think before we make the next coding steps here, we should get some feedback from the core team, what they think about the key aspects?

Carlitus’s picture

I've see that this doesn't work with managed_file and i don't know why.

It shows in the right position but when you select a file the ajax doesn't work well and disapears.

Carlitus’s picture

New patch to support managedFile and Ajax Callback.

I think this is not the best way to do it, but now al least works in my manual tests. I am sure that a person with more control of the core can do it in the most appropriate way.

I've see that the problem was when in the ajax callback to upload the file, the preRenderGroup was not needed and i've make a unset of the #groups in uploadAjaxCallback to skip this function.

Carlitus’s picture

FileSize
8.12 KB

New patch, the last one was wrong