Layout Builder attempts to determine if a block has renderable content or not. This is located within \Drupal\layout_builder\EventSubscriber\BlockComponentRenderArray::onBuildRender.
$content = $block->build();
$is_content_empty = Element::isEmpty($content);
$is_placeholder_ready = $event->inPreview() && $block instanceof PreviewFallbackInterface;
// If the content is empty and no placeholder is available, return.
if ($is_content_empty && !$is_placeholder_ready) {
return;
}
If the block can be previewed and the content is empty, the block has the placeholder text assigned:
if ($is_content_empty && $is_placeholder_ready) {
$build['content']['#markup'] = $this->t('Placeholder for the @preview_fallback', ['@preview_fallback' => $block->getPreviewFallbackString()]);
}
This causes a problem with formatters which use lazy builders and may return an empty render array. This is the case with Drupal Commerce and the add to cart field formatter.
The formatter will always return a lazy builder definition.
$elements[0]['add_to_cart_form'] = [
'#lazy_builder' => [
'commerce_product.lazy_builders:addToCartForm', [
$items->getEntity()->id(),
$this->viewMode,
$this->getSetting('combine'),
$langcode,
],
],
'#create_placeholder' => TRUE,
];
But the lazy builder could return an empty array
public function addToCartForm($product_id, $view_mode, $combine, $langcode) {
if (!$product_id) {
return [];
}
This is loosely related to #3027653: Allow block and layout plugins to determine if they are being previewed. But I think Layout Builder needs to execute returned lazy builders during the preview steps to properly handle preview callbacks.
Comments
Comment #9
idiaz.roncero+1.
This also happens with Flag module.
Expected behavior:
- A Layout Builder region that includes only a flag shouldn't render when the user hasn't access to the flag (i.e. anonymous)
Current behavior:
- Layout builder renders the region as the flag uses a lazy builder.