Not possible to change weight of entity form field widget in hook_form_alter()

Created on 21 May 2019, about 5 years ago
Updated 16 April 2024, 2 months ago

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.

πŸ› Bug report
Status

Needs work

Version

11.0 πŸ”₯

Component
EntityΒ  β†’

Last updated about 7 hours ago

Created by

πŸ‡¬πŸ‡§United Kingdom Rob230

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States mrweiner

    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.

  • Status changed to Needs review over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States mrweiner
  • Status changed to Needs work over 1 year ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    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.

  • πŸ‡¬πŸ‡§United Kingdom alexharries

    +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

  • First commit to issue fork.
  • πŸ‡©πŸ‡ͺGermany Ammaletu Bonn, Germany

    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"?!

  • Status changed to Needs review 5 months ago
  • πŸ‡©πŸ‡ͺGermany Ammaletu Bonn, Germany

    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.

  • Pipeline finished with Failed
    5 months ago
    Total: 281s
    #93170
  • Status changed to Needs work 5 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

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

  • Pipeline finished with Success
    4 months ago
    Total: 487s
    #96927
  • Status changed to Needs review 4 months ago
  • πŸ‡©πŸ‡ͺGermany Ammaletu Bonn, Germany

    I fixed the linting issue.

  • Pipeline finished with Canceled
    4 months ago
    #98957
  • Pipeline finished with Canceled
    4 months ago
    #98958
  • Pipeline finished with Canceled
    4 months ago
    #98959
  • Pipeline finished with Success
    4 months ago
    #98960
  • Status changed to Needs work 4 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    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.

  • πŸ‡©πŸ‡ͺGermany Ammaletu Bonn, Germany

    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".

  • Pipeline finished with Failed
    2 months ago
    Total: 561s
    #148123
Production build 0.69.0 2024