Several elements are not rendered inside the content region in the XB preview iframe

Created on 22 April 2025, 5 months ago

Overview

I have noticed that the preview rendered inside the iframe in XB is missing some elements that are present when viewing the live version of the same node.

Screenshot 1 shows the DOM inside the iframe of this simple node in XB.

In this first screenshot, labelled 1 and 2, you can see the .region--content div and the H1 (which is the SDC I have added to the layout.)

Now, look at Screenshot 2. This shows the DOM of the node when viewed by an anon. user.

In this second screenshot I have labelled the same .region--content and H1 tag with 1 and 2. You will see that between the two labelled elements a number of extra elements are rendered.

Finally, in both screenshots, I have drawn a green box around the styles for the H1 tag. In screenshot 1, a number of styles are applied to the H1 tag in error. The selectors for the style .layout--pass--content-medium > * etc use the > direct descendant selector and, in this case, that is the H1 tag. I believe they are intended to be applied to the <article> element that is the direct child of .region--content in screenshot 2. Having them apply to the H1 tag is causing the layout in some cases to be very broken.

Proposed resolution

The HTML structure seen in the live version of the page (screenshot 2) should be present in the XB preview markup (screenshot 1)

User interface changes

šŸ› Bug report
Status

Active

Version

0.0

Component

Page builder

Created by

šŸ‡¬šŸ‡§United Kingdom jessebaker

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

Merge Requests

Comments & Activities

  • Issue created by @jessebaker
  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Just discovered this issue. Will have to investigate this. Self-assigning. But if somebody else wants to investigate: please go ahead! I'll comment again prior to starting to investigate.

  • šŸ‡ŖšŸ‡øSpain penyaskito Seville šŸ’ƒ, Spain šŸ‡ŖšŸ‡ø, UTC+2 šŸ‡ŖšŸ‡ŗ

    olivero/node.html.twig template is not rendered on the XB preview and olivero_preprocess_node is not being triggered.

    That's why you also don't see the "authored by" meta.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    D'oh, of course! Thanks for investigating, @penyaskito!

    šŸ¤” Not sure what to do here. I bet we could try to figure out a way to render the XB component tree inside the node.html.twig template (writing this on phone, can't quickly read node.html.twig to make sure). But … that kinda goes against the spirit/point of XB.

    So, assigning to @lauriii to post his 2 cents about how he expects this to work 😊

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ
  • šŸ‡«šŸ‡®Finland lauriii Finland

    šŸ¤” Not sure what to do here. I bet we could try to figure out a way to render the XB component tree inside the node.html.twig template (writing this on phone, can't quickly read node.html.twig to make sure). But … that kinda goes against the spirit/point of XB.

    Nodes should be rendered using node.html.twig so long as Content Templates are not involved. When a Content Template is defined for Content Type, it would essentially take over the rendering and no longer use node.html.twig. This shouldn't be a massive problem because unless you have defined a Content Template, there aren't any slots to edit in XB.

  • Status changed to Needs work about 1 month ago
  • šŸ‡ŗšŸ‡øUnited States effulgentsia

    Removing "stable blocker" tag but we'll want to fix this as part of the Content Templates work, so setting the issue parent accordingly.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    #6: that does not make sense to me because node.html.twig contains this:

    <article{{ attributes }}>
    
      {{ title_prefix }}
      {% if label and not page %}
        <h2{{ title_attributes }}>
          <a href="{{ url }}" rel="bookmark">{{ label }}</a>
        </h2>
      {% endif %}
      {{ title_suffix }}
    
      {% if display_submitted %}
        <footer>
          {{ author_picture }}
          <div{{ author_attributes }}>
            {% trans %}Submitted by {{ author_name }} on {{ date }}{% endtrans %}
          </div>
        </footer>
      {% endif %}
    
      <div{{ content_attributes }}>
        {{ content }}
      </div>
    
    </article>
    

    IOW, it'll at minimum result in

    <article>
      <h2>my article</h2>
      <div>{{ XB COMPONENT TREE HERE }}</div>
    </article>
    

    and in most cases in

    <article>
      <h2>my article</h2>
      <footer><div>Submitted by Lauri on Aug 12, 2025</div></footer>
      <div>{{ XB COMPONENT TREE HERE }}</div>
    </article>
    

    IOW: when using XB to present a node, I think it'd be supremely confusing to then still be partially out of control, instead of in control.

    Agreed with @effulgentsia that this closely connects to the Content Template work — this sounds like Content Templates need to have a "render in original template or not" flag? šŸ¤”

  • šŸ‡«šŸ‡®Finland lauriii Finland

    I'm not following which part of #6 doesn't make sense and what's the use case in which it wouldn't make sense. I would expect to be able to specify where the title and publishing information is rendered in the XB content template. The only questionable part is if we'd want to always wrap content rendered using a content template with some HTML element.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    I read #6 but in the opposite way šŸ™ˆ That explains my comment #9.

    Nodes should be rendered using node.html.twig so long as Content Templates are not involved.

    šŸ‘† I missed the "so long as" part! 😬

    Is this then basically just:

    diff --git a/src/EntityHandlers/ContentTemplateAwareViewBuilder.php b/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    index 1c242da0a..aa8194e5a 100644
    --- a/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    +++ b/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    @@ -13,6 +13,7 @@ use Drupal\Core\Entity\EntityViewBuilderInterface;
     use Drupal\Core\Entity\FieldableEntityInterface;
     use Drupal\canvas\Entity\ContentTemplate;
     use Drupal\canvas\Storage\ComponentTreeLoader;
    +use Drupal\Core\Render\Element;
     use Symfony\Component\DependencyInjection\ContainerInterface;
     
     /**
    @@ -126,6 +127,16 @@ final class ContentTemplateAwareViewBuilder extends EntityViewBuilder {
         // @see \Drupal\canvas\Entity\ContentTemplate::buildMultiple()
         // @see \Drupal\canvas\Plugin\DataType\ComponentTreeHydrated::toRenderable()
         $this->decorated->buildComponents($build, $entities, $displays, $view_mode);
    +
    +    // Avoid `node.html.twig` from being used.
    +    // @see \Drupal\Core\Entity\EntityViewBuilder::buildMultiple()
    +    $entity_type_key = "#{$this->entityTypeId}";
    +    $children = Element::children($build_list);
    +    foreach ($children as $key) {
    +      if (isset($build_list[$key]['#theme']) && $build_list[$key]['#theme'] == $entity_type_key) {
    +        unset($build_list[$key]['#theme']);
    +      }
    +    }
       }
     
     }
    

    ?

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Aaaaaaactually … 

            // We don't want to use the default theme template as preprocess functions
            // etc might make assumptions about various fields being present.
            // @see template_preprocess_node.
            // @todo Remove in https://www.drupal.org/i/3534128 when https://drupal.org/i/3524738 is fixed
            unset($defaults['#theme']);
    

    in

    \Drupal\canvas\EntityHandlers\ContentTemplateAwareViewBuilder::getBuildDefaults()</code< since July 4's 
                
                  
                  
                  šŸ›
                  PHPUnit Next Major tests failing 
                    Active
                  
                 AFAICT means this is already the case? šŸ˜„
    
    (@jessebaker reported this in April.)
    
    That AFAICT means that 
                
                  
                  
                  šŸ“Œ
                  [upstream] Revert work-arounds for 11.2 regression #3524738
                    Postponed
                  
                 (which means to remove that <code>unset

    ) should instead be marked

    āš ļø However, @jessebaker originally reported this for individual nodes' individual component trees, i.e. long before content templates were a thing.

    So, @lauriii, can you please confirm that we're intending to remove the ability to create one-off component trees for nodes and instead are shifting to requiring ContentTemplates to be created for them, which would mean that XB should refuse to allow editing the per-node component tree for now. That ability would only be restored once exposed slots are supported, which is out of scope for 🌱 [META] Content templates Active ?

  • šŸ‡«šŸ‡®Finland lauriii Finland

    That's correct. šŸ‘

  • Now that this issue is closed, please review the contribution record.

    As a contributor, attribute any organization helped you, or if you volunteered your own time.

    Maintainers, please credit people who helped resolve this issue.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Well then … we do NOT have an issue yet in the queue nor linked from 🌱 [META] Content templates Active to refuse that. This issue will need to be rescoped to handle that.

    This will deeply affect any site that installs Canvas beta1, creates article nodes with individual component trees, then updates to 1.0, only to find out all their article nodes' component trees are no longer editable. Which means this actually arguably even should be a beta blocker! šŸ˜…

    P.S.: closed šŸ“Œ [upstream] Revert work-arounds for 11.2 regression #3524738 Postponed based on #13 confirming the bold part at the bottom of #12.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    In addition to #15, we'll still need

    • test coverage: NodeTemplatesTest should test that nothing of node.html.twig is rendered in either the preview or on the live site
    • a follow-up to remove the checkbox at /admin/structure/types/manage/article, or at least mark it as having zero effect when rendered using Canvas — similar to šŸ› Disable Block UI for regions managed by Experience Builder Active — because using Canvas will make this have zero effect
    • … probably more things I'm forgetting
  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Thanks to \Drupal\canvas\Hook\ContentTemplateHooks::entityTypeAlter() all of this already applies to all (fieldable) content entity types, and specifically exempts Canvas' own Page content entity type because it does not contain any structured data.

    We should update the existing comments to remove the obsolete @todos which justified a temporary state, and now state why this should become a permanent state:

    diff --git a/src/EntityHandlers/ContentTemplateAwareViewBuilder.php b/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    index 1c242da0a..f0273021e 100644
    --- a/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    +++ b/src/EntityHandlers/ContentTemplateAwareViewBuilder.php
    @@ -64,6 +64,7 @@ final class ContentTemplateAwareViewBuilder extends EntityViewBuilder {
       protected function getBuildDefaults(EntityInterface $entity, $view_mode) {
         $defaults = parent::getBuildDefaults($entity, $view_mode);
         $keys = NestedArray::getValue($defaults, ['#cache', 'keys']);
    +    // @todo only execute this if-branch if and only if a ContentTemplate exists for it.
         if ($keys !== NULL) {
           // This entity has render caching, so add a cache key indicating whether
           // or not it's opted into Canvas.
    @@ -71,10 +72,9 @@ final class ContentTemplateAwareViewBuilder extends EntityViewBuilder {
           try {
             $this->componentTreeLoader->getCanvasFieldName($entity);
             $keys[] = 'with-canvas';
    -        // We don't want to use the default theme template as preprocess functions
    -        // etc might make assumptions about various fields being present.
    -        // @see template_preprocess_node.
    -        // @todo Remove in https://www.drupal.org/i/3534128 when https://drupal.org/i/3524738 is fixed
    +        // We don't want to use the default theme template (such as
    +        // `node.html.twig`) because any content entity type that uses Canvas'
    +        // ContentTemplates is opting in to full control via Canvas.
             unset($defaults['#theme']);
           }
           catch (\LogicException) {
    diff --git a/src/Hook/ContentTemplateHooks.php b/src/Hook/ContentTemplateHooks.php
    index 3981b3714..b984e5a61 100644
    --- a/src/Hook/ContentTemplateHooks.php
    +++ b/src/Hook/ContentTemplateHooks.php
    @@ -73,7 +73,14 @@ final class ContentTemplateHooks {
           if ($entity_type->id() === Page::ENTITY_TYPE_ID) {
             continue;
           }
    -      // Canvas can only render fieldable content entities.
    +      // Canvas can only render fieldable content entities. Any content entity
    +      // types with structured data (all of them except Canvas' own `Page`)
    +      // must be assumed to use ContentTemplates, and hence should use that view
    +      // builder.
    +      // Note: as soon as a ContentTemplate exists for a certain content entity
    +      // type + view mode, the original template will NOT be used anymore:
    +      // - not the view mode-specific one, such as `node--teaser.html.twig`
    +      // - not the generic one, such as `node.html.twig`
           if ($entity_type->entityClassImplements(FieldableEntityInterface::class)) {
             // @see \Drupal\canvas\EntityHandlers\ContentTemplateAwareViewBuilder::createInstance()
             $entity_type->setHandlerClass(ContentTemplateAwareViewBuilder::DECORATED_HANDLER_KEY, $entity_type->getViewBuilderClass())
    
  • šŸ‡«šŸ‡®Finland lauriii Finland

    What's the question to me here?

  • šŸ‡ŗšŸ‡øUnited States effulgentsia

    I think #13 answers #12's question to @lauriii.

    And yes, implementing what the issue title now says needs to block the beta1 release, since it's a significant BC break of site data for sites that have already created component trees for individual nodes (articles). We'll need to include release notes that instruct people to manually copy (yay for copy/paste functionality in Canvas!) those component trees from nodes to page entities before they update their site to beta1 (or alphaN if there's an alpha tag that includes this removal prior to the beta1 tag).

  • šŸ‡«šŸ‡®Finland lauriii Finland

    Agreed that we should disable this before beta to avoid the BC break šŸ‘

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    This will AFAICT have MASSIVE repercussions for tests. For example, I just reviewed @tedbow's šŸ“Œ Refactor(or attempt to) all or most ApiLayoutController*Test classes to also test ContentTemplate entities Active , which is generalizing all canvas.api.layout.* tests to no longer test only Node but also test ContentTemplate.

    What we concluded here AFAICT means that all those tests ought to be updated to use the Page content entity type instead? šŸ˜…

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Will discuss this team-wide and circle back here.

  • šŸ‡§šŸ‡ŖBelgium wim leers Ghent šŸ‡§šŸ‡ŖšŸ‡ŖšŸ‡ŗ

    Conclusions:

    1. this issue: pragmatic approach: disallow editing any content entity besides the Page content entity
    2. this issue: remove the requirement "must have canvas field" requirement for now, which means:
      diff --git a/docs/config-management.md b/docs/config-management.md
      index 4dbaa6d3a..e8c604a96 100644
      --- a/docs/config-management.md
      +++ b/docs/config-management.md
      @@ -270,13 +270,15 @@ A `ContentTemplate` config entity can be created by Ambitious Site Builders to a
       
       When rendering content entities, a content template will be used to render the entity if, and _only_ if, two things are true:
       
      -1. The entity is opted into Drupal Canvas, which means it has an `Canvas field`.
      -2. There is a `ContentTemplate` for that content entity type and bundle, in the view mode that is being rendered.
      +1. There is a `ContentTemplate` for that content entity type and bundle, in the view mode that is being rendered.
      +2. The content entity type is `Node`.
       
       If a `ContentTemplate` is used for rendering a content entity, then `hook_entity_display_build_alter()` will NOT be invoked for that entity, because that hook (and all its implementations) assume field formatters are used to render (all or some) fields in sequence, which is not the case when using Canvas.
       
       āš ļø Still to be built:
       - A UI to create content templates, and manage existing templates: https://www.drupal.org/i/3518248
      +- Later, when support for exposed slots is added, a second requirement will be added: "The entity is opted into Drupal Canvas, which means it has an `Canvas field`.")
      +- Later, after https://www.drupal.org/project/experience_builder/issues/3498525, remove the second requirement: support more than just `Node`.
       
       ### 3.6 `StagedConfigUpdate` config entity
      
    3. new (follow-up) issue: update ALL tests that are currently testing Node and use Page instead. Then once exposed slot support is added, bring back test coverage for Node, and expand its test coverage to ensure that the necessary affordances + restrictions are in place (affordances to convey what is editable and isn't, restrictions in that it should be verified that no component instances living in the ContentTemplate can be modified)
  • Merge request !61Issue #3520487 "Refuse editing node" → (Merged) created by penyaskito
Production build 0.71.5 2024