Closed (fixed)
Project:
Display Builder
Version:
1.0.x-dev
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
19 Aug 2026 at 11:59 UTC
Updated:
14 Sep 2026 at 11:35 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
pdureau commentedThanks for taking care of this.
To be able to finish #3542796: Preview of view sources we need placeholders with the name of the source in the label, instead of '[Placeholder] No preview'.
Comment #4
mogtofu33 commentedComment #5
mogtofu33 commentedFor review, it include #3542796: Preview of view sources
Comment #6
pdureau commentedSuch huge MR is putting an undue burden on the reviewer. Let's try to keep topics well defined and well scoped.
Placeholders scope
Code review
I don't say this is necessarily wrong, maybe the work done here is broader than my initial understanding, but I was naively expecting a change covering only:
$this->buildPlaceholder($this->t('[Placeholder] No preview')by a dynamic value with the label of the source plugin, and the removal ofalterPreviewPlaceholder()So, I am surprised this change is needing so much additions:
DisplayBuilderHelpers::markSampleEntity(), used inEntityViewandInstance.RegionPlaceholderSourceTraitwith::buildBlockRegion()⚠️ The code, like other parts of the module, is using both "region" and "slot" terms. Not a big deal, but we may talk about terminology in a future ticketSpecific to blocks:
BlockSourcefrom UI Patterns. ⚠️ Those source overrides are not mean to stay so can we avoid adding more? ⚠️ Why are we manipulatingcontext_requirements(soon to be deprecated) here?BlockRegionPlaceholderTraitused inBlockPlaceholderTraitandBlockSourceBlockPlaceholderTraitused inPreviewPanelandBuilderPanelSpecific to
display_builder_page_layout:PageRegionSourceBaseusingRegionPlaceholderSourceTraitand extended byMainPageContentSourceandPageTitleSourceI need to continue the review, but it is a bit intimidating.
getPropValue() outside of Display Builder
⚠️
PageRegionSourceBase::getPropValue()andViewsUiPatternsSourceBase::getPropValue()directly return a placeholder instead of the expected value. I guess they are replaced later by the real value if possible.However, once the UI Patterns contexts will be tidied, some of those source plugins will show up outside of Display Builder, in the broader UI Patterns ecosystem. Will they work as expected?
Feature review
Just starting:
#3542796: Preview of view sources scope
The other MR content has been put here with some modifications. There may be a reason, but splitting the works (this ticket only for placeholders fix, the other ticket for the source previews), and validating changes one by one is usually helpful to avoid taking shortcuts.
With those main changes:
views_pre_executehook inCountViewExecutionsViewsUiPatternsSourceBaseis now usingRegionPlaceholderSourceTraitReview in progress.
Third scope?
Are those changes related to placeholders? Part of #3615194: Dynamic rules for wrapping in PreviewPanel? Or something else?
DisplayBuildableInterface::getPreviewPagePath()inEntityViewOverrideandViewDisplayPreviewRenderCacheservice decoratingrender_cache⚠️ active on every request when the module is activated. Is it not too "bold"? Do we need specific tests?DisplayBuilderHelpers::previewedInstanceId(), used inDenyPreviewSubRequest,DisplayBuildablePluginBase,ApiPreviewControllerandPreviewRenderCacheDisplayBuildableInterface::getSourcesForRender(), implemented ingetSourcesForRender()used instead of::getSources(), once of each module: inEntityViewDisplayTrait,PageLayoutPageVariantandPreprocessViewsViewComment #7
mogtofu33 commentedGot the complaint on the size, will split the MR in 3 to ease review.
The block menu do that when it is empty, When filled it's correct.
It seems like a special case for block menu, we have many different cases between block system, block with lazy_builder to be able to detect when empty or lack of content. Probably more a follow up as we probably have a much use cases as this kind of blocks are used...
Comment #8
pdureau commentedThanks you 🤗
Comment #9
mogtofu33 commentedComment #10
mogtofu33 commentedSplit into three, per #16742446. This issue is now placeholders only.
Current MR !351 rewritten: one commit, 38 files. The other two scopes moved out:
Both depend on this one and carry its commit, so they only add their own on top. Landing order is A, then B, then C.
What stays here: a placeholder is named by whoever knows best. A source that can never resolve in a builder answers for itself at any depth (RegionPlaceholderSourceTrait, page regions, chrome blocks). A panel that renders a node and gets nothing back names it from the block definition (BlockPlaceholderTrait), so Canvas and Preview agree. Plus markSampleEntity, which stops an unsaved sample entity taking down the render around it, and a log line on a swallowed render failure.
Also added the kernel test you asked for on PreviewRenderCache — it moved to #3618618: Preview an entity view override and a view page display on their own page with the rest of that scope. It asserts the decorator is inert outside the preview sub-request as carefully as it asserts it works inside one.
Two of your points still open:
context_requirementsin BlockSource is read, not manipulated: inBuilderSurface() checks whether RequirementsContext carries BUILDER_SURFACE. It needs a migration answer when contexts are tidied, but it adds no new write.PageRegionSourceBase::getPropValue()returning a placeholder outside Display Builder is a real gap.ViewsUiPatternsSourceBaseguards it properly, page layout does not.Follow-up for the footer menu: an empty block nested in a slot gets a placeholder in Canvas and nothing in Preview, because Preview only judges root nodes. Separate issue.
Comment #11
pdureau commentedThanks for the split, there are now
+1659/−311lines to review instead of+3347/-467👍Note to myself: The reviews must be done following this order:
So starting with this one.
Comment #12
pdureau commentedFirst feedback: just thinking out loud, in the flow of the review, I may write silly things here. I keep the ticket on my side until the review is finished.
Placeholders directly managed by sources
That sounds cool. I will try to write here my understanding, just to be sure.
There was 2 different placeholders logic in Display Bucodeilder:
BuilderPanel::buildSingleBlock(), we render a placeholder:system_messages_blockandlocal_tasks_blockblock pluginsPreviewPanel::alterPreviewPlaceholder(), we render a placeholder only (and always) for a curated selection of sources:local_tasks_block&system_messages_blockdisplay_builder_page_layout:main_page_content&page_titledisplay_builder_page_views, but it is a temporary situation until #3542796: Preview of view sourcesSo, by introducing
RegionPlaceholderSourceTrait::buildRegionPlaceholder(), we moved the management of placeholders to the source plugins themselves:BlockSourcewithFORCE_PLACEHOLDERMainPageContentSource&PageTitleSource(throughPageRegionSourceBase)That's cool. ⚠️ It was initially a bit complicated to understand because of the use of the word "region" here.
💡 By the way, does PreviewFallbackInterface::getPreviewFallbackString() (implemented in Core Block plugins and used in Layout Builder) would help us here?
⚠️ It may be bigger than that. I will check again.
DisplayBuilderHelpers::markSampleEntity()
Used in
EntityView::getRuntimeContexts()andInstance::refreshContexts(), that's a nice idea to reusein_previewfrom Core:Even if I don't really know what Core is doing with this information :)
⚠️ It is not directly related to the current work, but we are altering the logic here, so I am asking: Why do we have
Instance::refreshContexts()by the way? Is it a leftover of previous architecture (before the buildable plugins) ?There is nothing related to, or own by, the instance data in this method. It seems the logic can move to
EntityView, alongside::markSampleEntity().IslandPluginManagerInterface::BUILDER_SURFACE
Indeed. ⚠️ I will have a little look.
💡 By the way, just saying, there is also PreviewAwarePluginInterface for plugins, which seems to cover similar needs in Layout Builder.
Placeholders from ::getPropValue()
If it is OK for
ViewsUiPatternsSourceBase, I belive we are good for now, because the recent addition ofpagecontext (type:url), inPageLayoutSource,MainPageContentSourceandPageTitleSource, will act as a safeguard oncecontext_requirements: ['page']will be "disabled" (and later removed) in UI Patterns side.Instead of being context free and show up on every source selectors, those source plugins will be available nowhere because
pagecontext (type:url) is never injected in UI Patterns.Comment #13
pdureau commentedPlaceholders directly managed by sources
Tested with Page Layout in a fresh install and UI Suite DaisyUI:


It seems"[Page] Title" is the problematic one here, for 2 reasons:
This is not related with having 2 "[Page] Title" in a display. I have similar results with a single one .
Do you have similar results?
IslandPluginManagerInterface::BUILDER_SURFACE
Still investigating.
Comment #14
mogtofu33 commentedPage title fixed, other problems where from this one.
Then for 'Main navigation', this is probably the 'empty menu' issue that will need a follow up. Until then add at least one link in each used menus.
Comment #15
pdureau commentedPlaceholders directly managed by sources
✅ "[Page] Title" is fixed. Thanks.
It may be more than an empty menu issue. Let's also try with 2 other sources, all rendering empty markup:
Results:

3 problems:
sl-card.db-placeholder-buttoninstead ofdiv.db-placeholder-region)So, we may have a wording issue here.
.db-placeholder__region-helpis currently displaying:Which are not always describing correctly what is happening and may be confusing (Will users guess they are placeholder? Care about the Drupal module name?).
I am not a wording expert, but we can try something a bit like that:
What do you think?
IslandPluginManagerInterface::BUILDER_SURFACE
The goal would be to not increase our usage of
context_requirementswhich will be deprecated and removed. Moreover, the current proposal is extending this usage to a new plugin type: Display Builder's Islands, while it was used only with UI Patterns' sources until now.The goal is to tell
BlockSourceit is in a visual builder instead of the "real" display, that's it?Maybe it is the opportunity of using
PreviewAwarePluginInterfacealready discussed in this thread. So instead of using context requirements, can we do something like that?In src/Island/RealRenderTrait.php:
In src/Plugin/UiPatterns/Source/BlockSource.php:
Comment #17
mogtofu33 commentedPlaceholders are fixed, I have a problem with the PreviewAwarePluginInterface proposal, I think this would be way better in ui_patterns no?
setInPreview() cannot carry the flag from our side. In RealRenderTrait::buildComponentRealRender(), $source is the component source. The BlockSource we need is created later, inside ComponentElementBuilder::buildSource() → SourcePluginManager::getSource(), at arbitrary depth, and we never hold a handle to it. On a layout with system_breadcrumb_block inside a grid slot, the patch would flag the grid and leave the breadcrumb untouched, which is the exact case the source-level placeholder was added for. Root nodes do not rescue it either: ViewPanelBase discards the source it just created and buildSingleBlock() builds a fresh one.
That is why it currently reads context_requirements: the contexts array is the only thing that reaches a nested source, propagating verbatim through buildProps()/buildSlots() and re-emitted as #source_contexts by ComponentSource. Swapping RequirementsContext for a plain Context would work, but it is the same mechanism.
The real fix is for SourcePluginManager::getSource() to call setInPreview() on the instance it creates, from a flag the caller sets on the manager. That reaches any depth, serves every source with a builder/preview distinction rather than just ours, and lets us drop the context_requirements read entirely.
Here is a proposition of UI Patterns patch and a new branch here to review with this patch: 3618072-preview-aware-sources (failing ci is from missing patch ui_patterns, and views failure on playwright would be fixed in the views placholders mr).
Comment #18
mogtofu33 commentedComment #19
pdureau commentedPlaceholders directly managed by sources
Nice. Tested with MR !357 and the UI Patterns patch, it looks good. ✅
In my opinion, this part is complete and OK 🎉. (and its implementation looks slicker in MR !357, that's great)
IslandPluginManagerInterface::BUILDER_SURFACE
Good idea. Stuff related to source plugins would be better on UI Patterns side, so it will be handled easier when we will tidy the source system, that's why we have this issue: #3572186: Use SourceWithSlotsInterface from UI Patterns
Thanks a lot. The new MR looks great and the patch is interesting.
Does that means every
SourceWithSlotsInterfaceimplementation (the existingPageLayoutSource, the upcoming #3591025: Add a ViewTemplateSource for slots, and any potential implementations: paragraphs, config components, BEF...) will need to manually pass the#in_previewrender property to the children renderable like that?$this->componentElementBuilder->buildSource(['#in_preview' => $this->inPreview], 'content', [], ...) ?? [];'#in_preview' => $this->inPreview,Is there a way to automate this somewhere? In
ComponentElementBuilder::buildSource()? If we find the good way of doing that, merging this to UI Patterns will be my priority so we are not blocked.(Also, if we inject a non empty array with
#in_previewproperty toComponentElementBuilder::buildSource()'s$buildparameter and the source is not valid/found, the method will return a non-empty array, and i don't know if it will mess with some later checks)DisplayBuilderHelpers::markSampleEntity()
I will address the
Instance::refreshContexts()topic in a dedicated follow-up ticket: #3618945: Tidy Instance methods. So we can focus onPreviewAwarePluginInterfaceand merge sooner.Comment #20
mogtofu33 commentedYou were right, $build was the wrong channel. Rewrote it.
$contexts is already automatic: every SourceWithSlotsInterface threads it to its children anyway, so a new implementation propagates this for free. That puts the automation where you asked, in buildSource(), reading a plain Context rather than a RequirementsContext.
Updated patch for ui_patterns.
Comment #21
pdureau commentedSo, if my understanding is right, in this updated proposal:
ui_patterns:in_previewboolean context in every islands fromIslandPluginManager::createInstance()ComponentElementBuilder::buildSource()ComponentElementBuilderis settingPreviewAwarePluginInterface::setInPreview()according to contextBlockSourceimplementsPreviewAwarePluginInterfaceand can execute its logic.I would prefer us to not use Drupal Context like that, because it will be a specificity to manage during our current efforts to tidy contexts for source plugins ([3540247], #3608162: Tidy source contexts...) but a "normal" boolean context is already better than using the custom
RequirementsContext, so it may be OK like that.I will work today on #3576385: Make sources rendering easier on UI Pattern side by adding:
$previewboolean parameter toSourceTreeRendererInterface::buildSource()PreviewAwarePluginInterfacelogicI tell you once its done.
Comment #22
pdureau commentedAre you OK with this https://git.drupalcode.org/project/ui_patterns/-/merge_requests/498/diffs ?
With this, in
RealRenderTrait::renderSource(), we can replace:by the same method with the new
$in_previewboolean set asTRUE:or by the new
::buildSources()(may returns a list of renderables):Are we still propagating as expected with this solution? Or do we need a context to propagate the way we want?
@just_like_good_vibes is currently reviewing and updating #3576385: Make sources rendering easier but we wait your agreement to merge.
Comment #23
mogtofu33 commentedYes to MR 498, with one addition. The $in_preview parameter only reaches the source that call creates. Nested sources are built later by the slot sources themselves, so it stops at the first level and a block inside a layout region for example never gets it.
Two lines in buildSource() fix it: when $in_preview is TRUE, write the flag into $contexts before resolving the source, then read it back for setInPreview(). The contexts are the one thing every slot source already passes down, so propagation is automatic and no sourceWithSlotsInterface implementation has to do anything. $build is untouched.
Proposed in MR546 with one extra commit on yours.
Comment #24
mogtofu33 commentedChanged from my MR, as you seems to want to avoid context:
The only thing to solve is depth: $in_preview reaches the source that call creates, but the ones nested below it are built later, so a block inside a layout region never sees it. Three places fix that without a context:
Only the last one adds anything to $build, and on the component element, not on a source's value. wdyt?
Comment #25
pdureau commentedOn UI Patterns side, we moved to a more specific issue: #3619208: Manage PreviewAwarePluginInterface in ComponentElementBuilder (because #3576385: Make sources rendering easier was raising other points of discussions).
So, I guess we are back to your patch, without the
$previewparameter. Let's talk at the weekly.Comment #26
pdureau commentedRTBC as soon as #3619208: Manage PreviewAwarePluginInterface in ComponentElementBuilder is merged on UIP side.
Comment #27
pdureau commentedFor information.
In #3540247: Map source contexts with enums, the "ui_patterns:in_preview" context key has been moved to the ContextNames PHP enum: https://git.drupalcode.org/issue/ui_patterns-3540247/-/blob/3540247-tidy...
Our ticket to adopt this enum is #3590817: Use UI Patterns' context names enum
Comment #28
pdureau commentedThe next release of UI Patterns 2.0.x is expected for Friday 28 August
Comment #29
pdureau commentedUI Patterns 2.0.20 has been released yesterday as expected
Comment #30
mogtofu33 commented