Problem/Motivation

Many advanced modules (IEF, paragraphs, address) etc. use form elements to expand simple form structures to their complex internal elements. Once you have these elements using hook_form_alter no longer works and you need to switch to an alternative:

  • Use #after_build
  • Use #process (probably not what you want)

Proposed resolution

Add some documentation on hook_form_alter to allow people to point to the alternatives.

Remaining tasks

User interface changes

API changes

Data model changes

Issue fork drupal-2909574

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:

Comments

dawehner created an issue. See original summary.

th_tushar’s picture

Issue tags: +Vienna2017, +Novice
ivan berezhnov’s picture

Issue tags: +CSKyiv18

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

j. ayen green’s picture

Taking a look at this. If it's already in-hand, please let me know.https://www.drupal.org/project/drupal/issues/2909574#

msankhala’s picture

Once you have these elements using hook_form_alter no longer works and you need to switch to an alternative.

@dawehner Can you please explain this bit further?

johnny_aroza’s picture

Status: Active » Needs review
StatusFileSize
new736 bytes

I have added the doc above the hook_form_alter api function and added the patch.

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

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dksdev01’s picture

Issue tags: +Seattle2019

Working on updated patch with updated text. thanks

dksdev01’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new767 bytes

Message updated as below:

+ * When you use form elements to expand simple form structures to their complex
+ * internal elements, hook_form_alter no longer works and you need to switch to
+ * an alternative :
+ *  1. #after_build
+ *  2. #process (probably not what you want)
larowlan’s picture

Status: Reviewed & tested by the community » Needs review

Please don't RTBC your own patch, thanks

sumit-k’s picture

@dawehner can you explain little bit more to replicate issue or give example cases ?

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.

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.

harpreet16’s picture

Assigned: Unassigned » harpreet16
harpreet16’s picture

StatusFileSize
new434.08 KB

The patch applies successfully with Drupal 9.1.x as well patch-applied.
The patch was tested by applying it v.i.a composer using "composer install" after adding below lines within "extra" of the composer.json file

        "patches": {
            "drupal/core": {
                "2909574-11": "https://www.drupal.org/files/issues/2019-04-12/hook-form-alter-doc-2909574-11.patch"
            }
        }
harpreet16’s picture

Status: Needs review » Reviewed & tested by the community
harpreet16’s picture

Assigned: harpreet16 » Unassigned
dagmar’s picture

Status: Reviewed & tested by the community » Needs work

I think this issue is not enough complete to be RBTC.

I few question I would like to see documented are:

  1. What are the differences between after_build and process?
  2. Which is the execution order?
  3. What use cases you can achieve with after_build and process?

Do we have any better documentation to link? I was only able to find:

core/lib/Drupal/Core/Render/Element/FormElement.php

Here is a list of properties that are used during the rendering and form processing of form elements:

* - #after_build: (array) Array of callables or function names, which are called after the element is built. Arguments: $element, $form_state.

* - #process: (array) Array of callables or function names, which are called during form building. Arguments: $element, $form_state, $form.

Which are basically the same thing without specifying any relevant difference.

dagmar’s picture

Issue tags: -Novice

Removing Novice tag until we have the answers to the question I made.

dagmar’s picture

I think most of my questions can be answered by writing in text what this diagram shows: https://www.drupal.org/docs/7/api/form-api/form-api-internal-workflow-il...

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.

johnalbin’s picture

Title: Document #after_build from the hook_form_alter documentation » Document how to alter forms when hook_form_alter won't work

Good find, Mariano!

Here's my comment from #1300290: In drupal_render(), element_info is not merged recursively, preventing #type from serving its purpose that is relevant:

From my quick count, there are at least 4 places where you can modify a form and late or early changes can muck up the rendering. Let's see…

  1. A module's hook_form_alter or hook_form_FORM_ID_alter.
  2. And then a theme's hook_form_alter or hook_form_FORM_ID_alter . I mention this separately because a module's implementation always comes before a theme's implementation.
  3. The #process functions
  4. The #after_build functions
  5. The merging of '#type' => 'form' defaults from \Drupal::service('element_info')->getInfo(). These defaults can be altered by a module or theme with hook_element_info_alter.
  6. The #pre_render functions on the form. The list of these functions can be altered by any previous form alteration
  7. The preprocess functions on a form-id-specific theme hook. While the "form" hook is always a #theme_wrappers where the form is pre-rendered, a form can contain a #theme hook based on the form ID or type of form (e.g. confirm_form)and, after a specific template suggestion is picked, the preprocess functions can alter variables and since the form is an un-rendered variable, the form can be once again altered.
  8. For each element in the form, the merging of #type defaults from \Drupal::service('element_info')->getInfo(). These defaults can be altered by a module or theme.
  9. The #pre_render functions on the elements
  10. The preprocess functions for the elements' theme hooks. You can alter the list of preprocess functions in hook_theme_alter

Oh, wait. That's 10 places.

Obviously, we shouldn't document this like I stated above. There are a lot of places we can alter a form. I think it makes sense to skip preprocess functions since you can technically do this, but it's more logically placed with theming/rendering. I think we should make an except for element info and pre-render, though.

  1. The 3 kinds of form_alter hooks
  2. #process
  3. #after_build
  4. The form type's default info using hook_element_info_alter
  5. #pre_render on the form element

Then for each element in the form:

  1. The element type's default info using hook_element_info_alter
  2. #pre_render on the element
johnalbin’s picture

Ah, man. I'm going through Drupal\Core\Form\FormBuilder::doBuildForm() and I just discovered that, while Drupal's render does call \Drupal::service('element_info')->getInfo(), the FormBuilder calls this same method before render is called. doBuildForm also recursively calls itself for each form element. Which means the order I specified in my previous comment is completely wrong.

I'll report back shortly.

johnalbin’s picture

This is maybe too much info, but here's what I figured out from the code in FormBuilder.php.

  1. The "form" #type's default properties are merged into the form array. The defaults can be altered in hook_element_info_alter().
  2. The three kinds of form_alter hooks are run (described above).
  3. The form array's #process property contains an array of functions. These functions allow for elements to expand to multiple elements, e.g., radios, checkboxes and files. Any of the previous form alteration methods can alter this list of functions.
  4. Then, recursively, for each element in the form:
    1. The element's #type default info is merged. Same as #1 above.
    2. The element's #process functions are run. Same as #3 above.
    3. The element's #after_build functions are run. Same as #5 below.
  5. The form array's #after_build property contains an array of functions. These functions allow the form to be altered before the form finishes building and is cached. Any of the previous form alteration methods can alter this list of functions.
  6. Any form element (including the root form) can have a #pre_render property that contains an array of functions. These functions are run when the form is being rendered and should only be used to alter the rendering and not for any significant form alterations. Any of the previous form alteration methods can alter this list of functions.

johnalbin’s picture

Status: Needs work » Needs review

I created a merge request for this issue.

johnalbin’s picture

jhodgdon’s picture

Status: Needs review » Needs work

Interesting how that shows up! I reviewed the merge request on the merge request page....

johnalbin’s picture

Status: Needs work » Needs review

I've made the changes Jennifer suggested.

jhodgdon’s picture

Status: Needs review » Needs work

Added some more comments for the latest patch, which mostly looks good. Sorry if I missed these before...

johnalbin’s picture

Status: Needs work » Needs review

Sorry if I missed these before

No worries. Your comments have been very helpful!

jhodgdon’s picture

Component: forms system » documentation
Status: Needs review » Reviewed & tested by the community

Thanks for all the iterations and attention to detail! Looks good to me. I'm going to change the component to Documentation at this point, as sometimes committers are looking for something quick to commit and the MR is not making any code changes.

catch’s picture

Status: Reviewed & tested by the community » Needs work

Looks good but a couple of minor comments.

anmolgoyal74 made their first commit to this issue’s fork.

anmolgoyal74’s picture

Status: Needs work » Needs review
jhodgdon’s picture

Status: Needs review » Needs work

Thanks, it's getting closer! I think it needs some work though...

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.

srilakshmier made their first commit to this issue’s fork.

srilakshmier’s picture

Status: Needs work » Needs review

Fixed punctuation issue based on the previous comment.

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.

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.

joachim’s picture

Status: Needs review » Needs work

Really useful addition to docs, just some nitpicks!

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.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.