Problem/Motivation

In a hook_form_alter() I have changed the weight of one of the form fields:

$form['field_my_field']['#weight'] = 54;

And it was having no effect. I spent ages trying to debug this and eventually debugged the entire form build process and discovered that the weight was reverting back to the value set in in the CMS.

The culprit is /core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php

/**
 * Process callback: assigns weights and hides extra fields.
 *
 * @see \Drupal\Core\Entity\Entity\EntityFormDisplay::buildForm()
 */
public function processForm($element, FormStateInterface $form_state, $form) {
  // Assign the weights configured in the form display.
  foreach ($this->getComponents() as $name => $options) {
    if (isset($element[$name])) {
      $element[$name]['#weight'] = $options['weight'];
    }
  }

  // Hide extra fields.
  $extra_fields = \Drupal::entityManager()->getExtraFields($this->targetEntityType, $this->bundle);
  $extra_fields = isset($extra_fields['form']) ? $extra_fields['form'] : [];
  foreach ($extra_fields as $extra_field => $info) {
    if (!$this->getComponent($extra_field)) {
      $element[$extra_field]['#access'] = FALSE;
    }
  }
  return $element;
}

It resets all of the weights to the ones in the options.

This seems like a bug to me. Surely the process stage is the wrong time to be resetting all the weights. It means you overwrite anything that people do by altering the form. It's also very misleading because there are a huge amount of resources on the internet saying that you can change it there when you actually can't.

Steps to reproduce

  1. Take an existing form, e.g. the edit form of a basic page.
  2. Add a form alter hook for that form and change the weight of one of the elements, e.g. switch the order of title and body.
  3. Visit the form and notice that the order of the form elements has not changed.

You can get around this problem by adding an #after_build and changing the weights there.

Proposed resolution

This method should only set the weight for form elements which don't have a weight set already.

Remaining tasks

none

User interface changes

If there are hooks changing the weight of form elements, this would have been ignored previously and will now be executed.

API changes

none

Data model changes

none

Release notes snippet

Previously, it was not possible to reorder form elements through a form alter hook by changing their weight. This now works as expected.

Issue fork drupal-3056053

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

Rob230 created an issue. See original summary.

rob230’s picture

Issue summary: View changes

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.

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.

manuel.adan’s picture

I run into this. In my case, the revision_log field provided by core has a fixed weight of 25 and cannot be configured in the form display settings, so any attempt of change it in an implementation of the form_hook_alter has no effect.

Field weights set at display settings have preference and cannot be altered. At least, it should be somehow documented.

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.

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.

gagarine’s picture

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

I'm surprise this does not impact more peoples.

I stumble on with webform where I wanted to add some stuff to the render array and was not able to control the weight.

johnpitcairn’s picture

Yeah this is a pain. It makes it very hard to reposition a field in code, or to position an added code-only element. You have to append your own process method to the form's #process array.

johnpitcairn’s picture

Title: Not possible to change weight of node form field widget in hook_form_alter() » Not possible to change weight of entity form field widget in hook_form_alter()
mrweiner’s picture

Here is a simple patch based on the suggestion in #6 that only sets the weight if it is not yet set. Not sure of unintended consequences of this but we'll see if tests choke.

mrweiner’s picture

Status: Active » Needs review
smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs tests, +Needs issue summary update

This issue is being reviewed by the kind folks in Slack, #needs-review-queue-initiative. We are working to keep the size of Needs Review queue [2700+ issues] to around 400 (1 month or less), following Review a patch or merge request as a guide.

As a bug this will need a test case.

Also issue summary update. Recommend using the default template.

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.

alexgreyhead’s picture

+1 to the patch at #13 - this issue is preventing me from adjusting the order of elements on the taxonomy term edit form.

Thank you @mrweiner :)

/A

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

ammaletu’s picture

I just ran into this bug when I was trying to resort form elements and it seemed really simple. I created a branch, pushed the patch from #13 and added a simple test case. The test failed without the patch and succeeded with it.

This is my first time contributing code with a branch, so help me out a bit with the next steps. :-) #15 mentioned an issue summary update. Not sure what is missing there. Also, does this need a change record? And then set it back to "needs review"?!

ammaletu’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs tests, -Needs issue summary update

Ok, I tried to put the previous issue summary inside the issue summary template and added some lines. I have removed the two tags and set this to "needs review" so that somebody can have another look at it.

smustgrave’s picture

Status: Needs review » Needs work

Opened the MR for the tests to run, but appears to have some linting issues.

ammaletu’s picture

Status: Needs work » Needs review

I fixed the linting issue.

smustgrave’s picture

Status: Needs review » Needs work

Applied some simple suggestions from myself for return types.

Ran the test-only feature and it passed, so seems the test needs to be tweaked slightly.

ammaletu’s picture

I had another look at the test I wrote and fixed some errors. The test looked OK, but wasn't actually testing anything because of an error in the routing configuration. To me, this looks OK now and I verified with a real module and hook that the original problem still shows up in Drupal and was not fixed in some way.

But still, the test succeeds even without the fix in `core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php`. I'm a bit lost why that is. Is something missing from the test form setup so that the bug is not triggered? Maybe somebody else has an idea? For now, this remains on "Needs work".

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.