First thing to say, I am not totally convinced that a) my use-case is legit, b) whether I am doing everything 'right' and c) where the fix should be done.
When I upgraded to v1.0 from the final RC I was unable to see any of my embedded entities (both in the WYSIWYG and when fully rendered).
I tracked it down to entity_embed's EntityReferenceFieldFormatter->build particularly these lines:
$build['#pre_render'][] = static::class . '::disableContextualLinks';
$build['#pre_render'][] = static::class . '::disableQuickEdit'; I have a custom entity that kinda works along the lines of a reusable version of Paragraphs. We call them embeddables and we have a mechanism to associate 'modifiers' with them at the point of embedding (see pull_quote.png) - in this case when a pull quote bundle is embedded the editors can pick whether the pull quote floats left, right or is in the middle (each bundle can have whatever modifiers make sense to it - it can get quite fancy). We use Entity Embed to embed these into the WYSIYWG (we also have page types that use embeddable to generate landing page ... our D7 site is rescue.org, a quick look will make things pretty obvious as to how we build our site).
Most of the complexity of the modifiers get handle in a custom EntityViewBuilder - so you pass in both the entity and the modifiers.
I decided to create a RenderElement to make the code usage easier e.g.
$build = [
'#type' => 'embeddable',
'#embeddable' => $embeddable,
'#view_mode' => $view_mode,
'#options' => $options, // array of whatever options make sense to this embeddable left, right, pink, blue etc
'#mode' => $mode, // enabled, test or disabled
]The RenderElement has a pre_render callback that takes the parameters passed in and ends up calling our custom EntityViewBuilder with the Embeddable entity and its modifiers (and view mode etc).
We have custom entity reference field/widget/formatters that extends the standard ones and basically handle the storage, capturing and rendering of an embeddable in the context of a 'entity reference' (like on a landing page or with entity embed). The formatter uses the RenderElement.
The challenge when we upgraded from RC to 8.1.0 was the removal of the contextual menu and the disabling of quick edit.
Inside the core render class there is this block of code:
if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
$elements += $this->elementInfo->getInfo($elements['#type']);
}What this does is combines the build array generated in EntityReferenceFieldFormatter->build with the RenderElement's "info" - because they both have #pre_render entries in their respective arrays the one from the RenderElement are lost, essentially, lost because of the natural of the + operator.
Obviously, I am pretty much 100% sure core is doing the right thing ... I wondered whether the Entity Embed code was 'allowed' to add those pre_render entries where it does ... but it also seemed pretty legit. In the end I dodged my way around it, as I had already subclassed EntityReferenceFieldFormatter I just overloaded the build method and made sure my RenderElement's #pre_render was included too.
I've marked this as minor, as I doubt there are many folks doing this ... and chances are I am doing something wrong.
| Comment | File | Size | Author |
|---|---|---|---|
| pull_quote.png | 55.27 KB | AndyThornton |
Comments
Comment #2
AndyThornton commentedComment #3
wim leersIs this returned by your
\Drupal\Core\Entity\EntityViewBuilderInterface::view()implementation?This was intentional. Are you saying you were using Contextual Links and Quick Edit on embedded entities?
Aha!!!!! I remember running into something like this too at some point a long time ago. A quick search revealed #2348459: Fields of type 'Text (formatted)' do NOT save values. which has an interesting work-around in
\Drupal\filter\Element\TextFormat::processFormat()which I think you might be able to copy :)This is frankly just one of the places where the Render API falls apart; it's an edge case that it was just not well thought out enough for. You've done nothing wrong, nor did Entity Embed, this is simply an area of unspecified behavior. Hence the need for that work-around.
Comment #4
wim leersComment #5
AndyThornton commentedI see, fair enough. I was not totally distraught about my workaround ... although ... isnt ideal, of course.
Answering your questions:
1) No. The RenderElement is returned by my custom Entity Reference Field Formatter. Aside from using Entity Embed, we also allow embeddables to be used on landing page ... so picture an unlimited entity reference field to generate 'rows' of embeddables. That needs to be custom because when we make that reference we also capture the modifiers (and view mode, for that matter). The pre_render method inside my RenderElement called 'view' on the custom entity view builder.
2) No. We were not using/relying on contextual editing in the WYSIWYG. It wouldnt matter what the entity embed pre_render does .. just the existence of them means the RenderElement's pre_render never gets called because of the way Renderer combines the arrays.
I am not adverse to just closing this ... it does seem edge case-y ...
Comment #6
petr illekHi all,
I've just updated Entity Embed from Beta 2 to 1.0 and cannot see the embeded entities in the CK Editor (images, nodes etc).
I'm sure I don't have any custom code used as AndyThornton, just couple of view modes using Display Suite.
I revert my update and start updating one version by one to see when it breaks. It was the last step from RC2 to 1.0.
Should I open a new issue for that as it is only a partially related to the original post?
Thanks a lot.