When Drupal\Core\Render\Renderer::doRender() processes #lazy_builder callbacks the #type defaults are already loaded, so any element with a #type property will not be rendered properly.

A #pre_render callback often adds new types in child elements only, when it becomes possible to have the type defaults loaded. With a #lazy_builder callback it's not common to return a child element.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Eric_A created an issue. See original summary.

Eric_A’s picture

Status: Active » Needs review
Issue tags: +Needs tests
FileSize
954 bytes

Something like this.

Eric_A’s picture

Title: Renderer does not allow for lazy builders to return types (defaults not loaded) » Lazy builder broken (#type defaults not loaded)
Eric_A’s picture

Issue tags: +D8 cacheability
Eric_A’s picture

Status: Needs review » Closed (works as designed)

I got confused. The observed behavior is the same as with the old, familiar #pre_render: to have element type defaults applied automatically, having child elements rendered is the only option.

Closing this one.

Eric_A’s picture

But then again, a #pre_render callback would normally add new types in child elements only. With a #lazy_builder callback it's different...

Eric_A’s picture

Status: Closed (works as designed) » Needs review

Back to Needs review because of #6.

Eric_A’s picture

Issue summary: View changes
Eric_A’s picture

Issue summary: View changes

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

xjm’s picture

Is there any example in core that can reproduce this bug, or is it possible to provide a short example snippet and steps to reproduce and test how it is not rendered properly?

Eric_A’s picture

Is there any example in core that can reproduce this bug

Not that I'm aware of.

is it possible to provide a short example snippet and steps to reproduce and test how it is not rendered properly?

$element = [
  '#lazy_builder' => [
    function($uri) {
      return [
        '#type' => 'more_link',
        '#url' => Url::fromUri($uri),
      ];
    },
    ['https://www.drupal.org'],
  ],
];

This element will not render as a more link. It would if the #lazy_builder callback returned a child element.
I'm not too sure this is a true bug. Our default renderer implementation shows the same behavior with #pre_render for ages. It's just not documented behavior.

Eric_A’s picture

Issue summary: View changes
Eric_A’s picture

Fixed ordering in the snippet.

Eric_A’s picture

And fixed the text that goes with it. It works if the #lazy_builder callback returns a child element.

Wim Leers’s picture

It would if the #lazy_builder callback returned a child element.

Exactly.

I'm not too sure this is a true bug. Our default renderer implementation shows the same behavior with #pre_render for ages. It's just not documented behavior.

Indeed.

But we should make a decision here, and then help the developer by throwing an assertion.

Eric_A’s picture

Here's a patch with the assert() approach, both for #lazy_builder and #pre_render.
If we leave the actual processing as is and confine ourselves to adding more assertions to Drupal\Core\Render, then the issue category should probably change from "Bug report" to something else and "D8 cacheability" should be removed in favor of "DX (Developer Experience)".

Status: Needs review » Needs work

The last submitted patch, 17: lazy-builder-type-2609250-17.patch, failed testing.

Eric_A’s picture

I've removed the #pre_render part assert(). I think it's impossible in the #pre_render part to determine fully within the assert() if a #type property was returned (wether one already existed or not, with the same or a different value.)

Status: Needs review » Needs work

The last submitted patch, 19: lazy-builder-type-2609250-19.patch, failed testing.

lauriii’s picture

Discussed with @alexpott, @xjm, @Cottser and @joelpittet. We agreed that this should remain as a major bug because this is very bad DX. It is very difficult to debug why render elements are not rendered properly on the lazy builder.

lauriii’s picture

Issue tags: +Triaged core major

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Upchuk’s picture

Hey there,

Last movement on this issue was quite a long time ago so it's worth looking at it again. I updated the docs on auto-placeholdering to mention this fact. I just lost 40 minutes figuring out why the heck my renderable was returning empty.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

lukasss’s picture

Version: 8.6.x-dev » 8.9.x-dev

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

bbu23’s picture

Thanks Upchuk for updating the documentation. I was having the same problem: wondering why my lazy builder was not working. I was checking core, but didn't notice the difference.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

quietone’s picture

Got this as a random bug at DrupalSouth sprint. This is still valid and needs a reroll and tests.

ravi.shankar’s picture

Added reroll of patch #19 on Drupal 10.1.x.

larowlan’s picture

An alternative approach here would just be to call this on the $new_element

if (isset($elements['#type'])) {
  $element += $this->elementInfo->getInfo($elements['#type'])
}

larowlan’s picture

joachim’s picture

#39 That sounds useful but I'm concerned it's a bit hacky to call getInfo() from a new place.

larowlan’s picture

It's roughly 10 lines below where the renderer already calls it (off the top of my head when I hit this issue yesterday)

andypost’s picture

+1 to #39

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.