Handle components without HTML wrappers

Created on 9 April 2025, 8 days ago

Overview

When a component is placed it is assumed that it contains at least some HTML, which is wrapped in comments and has a data attribute attached so the XB UI can manipulate it.

However, it is not mandatory for components to output any HTML at all, e.g. if the component contains defensive code such as

{% if image and image.src %}
  <img src="{{ image.src }}" alt="{{ image.alt }}" />
{% endif %}

It is also possible for a component to output text, but not HTML.

Proposed resolution

When we are previewing a component that does not contain any HTML tags, detect this special situation and wrap them in a container, so they can still be previewed and manipulated correctly by the UI.

User interface changes

📌 Task
Status

Active

Version

0.0

Component

Page builder

Created by

🇬🇧United Kingdom longwave UK

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

Comments & Activities

  • Issue created by @longwave
  • 🇬🇧United Kingdom longwave UK
  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    More context: #3509608-54: Unable to save an optional image with its default value (because it does not correspond to a Media entity): allow saving DefaultRelativeUrlPropSource .

    When we are previewing a component that does not contain any HTML tags, detect this special situation and wrap them in a container, so they can still be previewed and manipulated correctly by the UI.

    How do you propose doing that for code components?

    Wouldn't be more accurate?

  • 🇬🇧United Kingdom longwave UK

    There is nothing stopping an SDC or a block outputting a text string only, with no surrounding tags? I haven't tested but I think this would render as text in the preview but would not be draggable as there is no element to receive the click.

    Code components are more tricky and would require hooking into the Astro renderer I guess, I haven't thought about or looked into that yet. Perhaps that can wait for a separate issue.

  • 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺

    I knew there were existing issues for this problem space already, but couldn't find them. Just stumbled upon one: 🐛 [Needs design] Previews of pages containing (dynamically) empty blocks are malformed Active .

    That's basically the same problem:

    1. Depending on explicit input ("settings" for block plugins, "props" for SDCs), the block may result in an empty render array to render:
          $content = $block->build();
          if (Element::isEmpty($content)) {
            $content['#access'] = $access;
            return $content;
          }
      

      \Drupal\experience_builder\Plugin\ExperienceBuilder\ComponentSource\BlockComponent::renderComponent()

    2. Core has a solution for this: PreviewAwarePluginInterface, but nothing in core actually uses this to render an alternative representation; only Layout Builder does it in a heavy-handed way:
            if ($event->inPreview()) {
              if ($block instanceof PreviewFallbackInterface) {
                $preview_fallback_string = $block->getPreviewFallbackString();
              }
              else {
                $preview_fallback_string = $this->t('"@block" block', ['@block' => $block->label()]);
              }
              // @todo Use new label methods so
              //   data-layout-content-preview-placeholder-label doesn't have to use
              //   preview fallback in https://www.drupal.org/node/2025649.
              $build['#attributes']['data-layout-content-preview-placeholder-label'] = $preview_fallback_string;
      
              if ($is_content_empty && $is_placeholder_ready) {
                $build['content']['#markup'] = $this->t('Placeholder for the @preview_fallback', ['@preview_fallback' => $block->getPreviewFallbackString()]);
              }
            }
      

    … we could use the same strategy, but wrap that string in a wrapper.

    Thoughts? And … should we just merge this into 🐛 [Needs design] Previews of pages containing (dynamically) empty blocks are malformed Active ? 😅

Production build 0.71.5 2024