Problem/Motivation
IEF displays entity form elements differently than it requires for its data structure (for storage). It does so by moving entity form elements into a fieldset wrapper in a pre_render callback. This makes it much harder to alter the form using general form hooks (instead of IEF-specific hooks) and is most likely no longer required with Drupal 8.
A similar issue was opened for field group (#2669904: Stop altering the form structure), where the solution offered is to use the #group property, and unlike field_group, we only have to deal with the widget side of things, not the formatter:
Its possible to nest form element without changing the actual form structure in D8. Sadly this is only supported in Form API and not in Render API, nevertheless there isa huge benefit because the form structure won't change with field group enabled and makes other form alter way more easier.
The code in \Drupal\inline_entity_form\Element\InlineEntityForm::addFieldsetMarkup already documents that this moving of elements is only applied for rendering the form:
Inline forms use #tree = TRUE to keep their values in a hierarchy for easier storage. Moving the form elements into fieldsets during form building would break up that hierarchy, so it's not an option for entity fields. Therefore, we wait until the pre_render stage, where any changes we make affect presentation only and aren't reflected in $form_state.
Proposed resolution
Use #group to group up entity form elements and make the form pretty, instead of forcibly moving elements around.
Remaining tasks
Decide if we can and want to do this, and if so implement.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | group_elements_without-2884444-2.patch | 5.28 KB | markhalliwell |
Comments
Comment #2
markhalliwellThere's actually no code (in this project) that is using the custom
#fieldsetproperty other than the custom #pre_render callback that implements the "logic". I think it's just safe to remove.Now, regarding
#group. This is a very touchy subject because 1) not a lot of people understand how they actually work and 2) how they actually work isn't very well documented; it's kind of just "magic".First, the custom
inline_entity_formrender element does not invoke the callbacksRenderElement::preRenderGroupandRenderElement::processGroupwhich are necessary to properly handle#groupproperties which produce things like nested details/fieldset and vertical tabs (see related issue).Second, the render array returned from an entity form build (and subsequent alter hooks introduced by this module) may not represent the correct
#groupidentifier. The correct#groupidentifier has since changed when the entity form's became nested and thus any of it's child element's#parentsand#array_parentsvalues changed with it. Thus, if one of those said child elements references a#groupthat is local or was newly introduced to said form, it would be ignored.The above patch aims to solve all the above. I have documented it quite well so it should be a pretty straightforward patch. Let me know if I need to explain it further.
Comment #3
darvanenGood patch and well explained, thanks. Looks good to me, setting RTBC because the only issue I see is a nit:
This is too long for a ternary operation i.m.o.
I don't think this issue is critical, it's not breaking anything, is it? I would even hesitate to call it a bug.
Comment #4
markhalliwellYes, it is and it is definitely a bug.
It implements a custom element type that doesn't call the parent
processGroupmethod it subclasses, so subsequent child elements do not receive the correct parent identifiers.Thus, when this element is introduced into any sort of "complex" render array, it doesn't conform to normal behavior and breaks existing functionality.
This is especially true when this element is nested inside vertical tabs (which greatly relies on
#group).Comment #5
darvanenFair enough, I stand corrected :)
Comment #7
bojanz commentedThanks!