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
- Take an existing form, e.g. the edit form of a basic page.
- 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.
- 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.
| Comment | File | Size | Author |
|---|---|---|---|
| #13 | entity-form-field-weights-d9--3056053--13.patch | 780 bytes | mrweiner |
Issue fork drupal-3056053
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
Comment #2
rob230 commentedComment #6
manuel.adanI 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.
Comment #10
gagarine commentedI'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.
Comment #11
johnpitcairn commentedYeah 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
#processarray.Comment #12
johnpitcairn commentedComment #13
mrweiner commentedHere 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.
Comment #14
mrweiner commentedComment #15
smustgrave commentedThis 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.
Comment #17
alexgreyhead commented+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
Comment #19
ammaletu commentedI 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"?!
Comment #20
ammaletu commentedOk, 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.
Comment #22
smustgrave commentedOpened the MR for the tests to run, but appears to have some linting issues.
Comment #23
ammaletu commentedI fixed the linting issue.
Comment #24
smustgrave commentedApplied 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.
Comment #25
ammaletu commentedI 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".