Problem/Motivation

#2953656: No ability to control "extra fields" with Layout Builder added extra fields in blocks and works for extra fields which were enabled / visible in the view mode before layout_builder was enabled.

When adding new extra fields for example via HOOK_entity_extra_field_info OR https://www.drupal.org/project/extra_field now, even if you add these to the layout as blocks, their content is not rendered. Their title is rendered, which is quite strange.

Vice-versa if you disable layout_builder, move the extra_field from "Disabled" into a visible region and then re-enable layout_builder, the extra field is visible.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

CommentFileSizeAuthor
#54 interdiff_46-54.txt1.29 KBdanflanagan8
#54 3069578--54.patch4.64 KBdanflanagan8
#46 3069578-46.patch4.1 KBayushmishra206
#46 interdiff_43-46.txt2.93 KBayushmishra206
#43 interdiff_39-43.txt2.12 KBdanflanagan8
#43 3069578--43.patch4.19 KBdanflanagan8
#40 3069578--39.patch3.91 KBdanflanagan8
#39 interdiff_37-39.txt2.38 KBdanflanagan8
#37 3069578--37.patch5.54 KBdanflanagan8
#33 3069578--33.patch5.68 KBdanflanagan8
#30 interdiff_29-30.txt1.14 KBdanflanagan8
#30 3069578--30.patch4.86 KBdanflanagan8
#29 3069578--29.patch4.83 KBdanflanagan8
#28 3069578--28--FAIL.patch2.48 KBdanflanagan8
#24 3069578--24.patch641 bytesdanflanagan8
#23 3069578--23.patch651 bytesdanflanagan8
#21 interdiff-3069578-14-21.txt1.11 KBandersen_ti
#21 missing_extra_fields-3069578-21.patch2.35 KBandersen_ti
#14 interdiff-3069578-12-14.txt1.23 KBYurkinPark
#14 missing_extra_fields-3069578-14.patch2.44 KBYurkinPark
#12 missing_extra_fields-3069578-12.patch1.38 KBwaspper
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Anybody created an issue. See original summary.

Anybody’s picture

Ok I found it!

Layout builder (or anything in the below function tree) considers the "hidden" area from the display configuration. If we remove the extra field manually from the

hidden:
  - my_extra_field

area, it appears correctly!

So the hidden should not be considered at all here.

If that problem doesn't only occur for extra fields, we should rename the issue accordingly to something like "Layout builder should not consider 'hidden' configuration." but I guess this also happened to other fields, someone already ran into it...

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

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Asterovim’s picture

Hello "Anybody" and thanks you.

I confirm that it works by deleting in hidden.

YurkinPark’s picture

To allow your field be visible on layout builder "add component" form, you have to set "visible = true" in definition.
Found the case when it is possible to successfully configure and export display config with layout builder enabled. Follow next steps:

  1. Configure your entity fully before managing displays
  2. Before enabling layout builder, add your filed to content area using default display manager
  3. Enable layout builder and configure you display

Second step is important, this will add field configuration in content

content:
  extra_field_your_field:
    weight: -30
    region: content
    settings: {  }
    third_party_settings: {  }

and will remove this field from hidden list.

Difference between regular fields and extra_filed fields is regular fields add its own configuration to display (to content area) when it is added, but extra_field fields don't have such trigger. Here is 2 possible solution:

  1. Add field configuration to content list during discovering of fileds
  2. Watch layout builder form and manage it after fields added
andypost’s picture

YurkinPark’s picture

@andypost issue us not related to visibility of blocks you can add, it is about render of display

YurkinPark’s picture

Follow this task for this issue #3069732: Problems with layout_builder and possibly this task can be closed i guess since problem is in extra_field module.

tim.plunkett’s picture

Status: Active » Closed (duplicate)
Issue tags: +Blocks-Layouts
Related issues: +#3069732: Problems with layout_builder

Yes, marking as a duplicate.
If someone can reproduce this without using that module (aka implementing hook_entity_extra_field_info() directly), please reopen with your code example.

waspper’s picture

Bug is present even using hook_entity_extra_field_info(). For example, le't asume we have following extra-field:

/**
 * Implements hook_entity_extra_field_info().
 */
function my_module_entity_extra_field_info() {
  $extra['node']['test']['display']['module_extra_field_test'] = array(
    'label' => t('Test module extra-field'),
    'description' => t('This is my own extra-field.'),
    'weight' => 100,
    'visible' => TRUE,
  );

  return $extra;
}

/**
 * Implements hook_node_view().
 */
function my_module_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
  if ($entity->bundle() == 'test' && $display->getComponent('module_extra_field_test')) {
    $build['module_extra_field_test'] = array(
      '#type' => 'inline_template',
      '#template' => '<div class="extra-field-test"><h2>{{ text }}</h2></div>',
      '#context' => [
        'text' => 'This is an extra-field test.',
      ],
    );
  }
}

Without Layout builder, field works fine. It's displayed by default (keep note on property 'visible' => TRUE, at first hook).

Then, if I remove field from display, and I enable layout builder and I try to re-add field, it doesn't work. Field content is not rendered. We could to think it's needed to disable layout builder to append field to the "base" display and then, re-enable it again. But this is not desired behavior, because there could be sites with complex layouts. Also, keep in mind "visible" is already enabled into the definition.

Seems problem could reside into the core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php::getComponent method. It returns "NULL" even for some core fields (for example, the node "Links" field).

waspper’s picture

Status: Closed (duplicate) » Active
waspper’s picture

Again: Just wanted to hear opinion: Attached patch is basically to ilustrate some issues. It would be great to know, if approach is concerning this class.

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.

YurkinPark’s picture

tim.plunkett’s picture

Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs reroll, +Needs issue summary update, +Needs tests
kostyashupenko’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Against 9.1.x branch reroll is not needed

andypost’s picture

Status: Needs review » Needs work

As patch fails

ravi.shankar’s picture

Assigned: Unassigned » ravi.shankar

Working on this.

ravi.shankar’s picture

Assigned: ravi.shankar » Unassigned
CulacovPavel’s picture

Notice: Undefined offset: 3 in Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay->preSave() (line 166 of core\modules\layout_builder\src\Entity\LayoutBuilderEntityViewDisplay.php).

list (, , , $field_name) = explode($plugin::DERIVATIVE_SEPARATOR, $plugin->getPluginId(), 4);

Fix this to

if($plugin instanceof ExtraFieldBlock){

            list (, , , $field_name) = explode($plugin::DERIVATIVE_SEPARATOR, $plugin->getPluginId(), 4);
            if(!isset($this->content[$field_name])){
              parent::setComponent($field_name);
            }
          }

to me working thanks

andersen_ti’s picture

super_romeo’s picture

Thanks for patch #21, but issue from #20 still exists.

danflanagan8’s picture

New to this issue here. I was working on #3144010: New pseudo-fields cannot be removed, InvalidArgumentException thrown and I think I solved this issue too. Can someone review this patch?

This patch modifies a class that does not exist in 9.0.x, so this will only apply on 9.1.x.

This patch does not work. See comment #27. Sorry!

danflanagan8’s picture

Here's a patch that uses the same approach as the one in #23 but it's for 9.0.x and it should work in 8.9.x.

This patch does not work. See comment #27. Sorry!

tim.plunkett’s picture

Issue summary: View changes
Status: Needs review » Needs work

NW for an issue summary update and for tests.

I have some other thoughts about the change and how best to document this code, but that should wait until after tests are written.

tim.plunkett’s picture

Status: Needs work » Closed (duplicate)
Issue tags: -Needs issue summary update, -Needs tests

Actually, closing this one in favor of #3144010: New pseudo-fields cannot be removed, InvalidArgumentException thrown as the fixes are the same.

danflanagan8’s picture

Status: Closed (duplicate) » Needs work
Issue tags: +Needs tests

Turns out I was totally wrong about my patches in #23 and #24 solving this issue. It is not a duplicate of #3144010: New pseudo-fields cannot be removed, InvalidArgumentException thrown.

Please see comment from @sorlov on the other issue: https://www.drupal.org/project/drupal/issues/3144010#comment-13825300

Sorry about the confusion. Re-opening this issue. I plan to post a fail test soon.

danflanagan8’s picture

Here's a FAIL patch that I think exposes the issue cleanly.

danflanagan8’s picture

Here's the patch from #21 tested against the FAIL patch of #28. The test passes locally, which is good news.

There's a comment in #20 that may or may not be resolved yet.

UPDATE:
I'm seeing failed tests with this message:

Notice: Undefined offset: 3
Drupal\layout_builder\Entity\LayoutBuilderEntityViewDisplay->preSave()() (Line: 166)

I think that's the same thing brought up in #20.

danflanagan8’s picture

FileSize
4.86 KB
1.14 KB

I incorporated the suggestion from #20 (from @Regnoy) into this latest patch. See interdiff and comment #20.

tim.plunkett’s picture

@danflanagan8 ah, okay that makes more sense :)

  1. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -157,6 +158,20 @@ public function preSave(EntityStorageInterface $storage) {
    +          if ($plugin instanceof ExtraFieldBlock) {
    
    @@ -479,6 +494,9 @@ public function getComponent($name) {
    +        if ($plugin->getBaseId() == 'extra_field_block') {
    

    I think the base ID should be checked in both cases.

  2. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -157,6 +158,20 @@ public function preSave(EntityStorageInterface $storage) {
    +              parent::setComponent($field_name);
    

    I've never seen parent:: calls to _other methods_ before. Why not call $this->setComponent?

    Additionally, why not do this in
    an override of ::init()?

    Or if it's possible, from within setComponent directly?

    Doing this on every preSave() doesn't feel right.

  3. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -479,6 +494,9 @@ public function getComponent($name) {
               return $configuration['formatter'];
    ...
    +          return $configuration;
    

    Can we possibly change ExtraFieldBlock to not need this special casing?

  4. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -535,7 +553,7 @@ private function getSectionComponentForFieldName($field_name) {
    +        if ($plugin instanceof DerivativeInspectionInterface && ($plugin->getBaseId() === 'field_block' || $plugin->getBaseId() === 'extra_field_block')) {
    

    Nit: This could use in_array()

  5. +++ b/core/modules/layout_builder/tests/modules/layout_builder_test/layout_builder_test.module
    @@ -47,6 +47,12 @@ function layout_builder_test_entity_extra_field_info() {
    +    'label' => t('Pseudofield 2'),
    +    'description' => t('Pseudofield description'),
    
    @@ -59,6 +65,11 @@ function layout_builder_test_node_view(array &$build, EntityInterface $entity, E
    +      '#markup' => 'Pseudofield 2 is hidden by default.',
    

    Idk where "pseudofield" comes from, let's call it an "extra field" like it is in the code base.

danflanagan8’s picture

Issue tags: -Needs tests

Idk where "pseudofield" comes from

That's so funny, @tim.plunkett! I learned these as "pseudofields" a few years ago and I toss it around as if it's the standard word. In the docblock for hook_entity_extra_field_info() it reads:

Exposes "pseudo-field" components on content entities.

Even core is a little bit confused on the matter! Anyway, changing the wording from "Pseudofield 2" to "Extra field 2" would be no problem.

As for your other comments on the patch, I haven't looked at the functional code in the patch too closely and I don't really understand what's going on. Other than the test part of the patch, I was mindlessly compiling previously posted patches and comments.

Maybe someone who worked on the previous patches could take a look?

danflanagan8’s picture

I took some time to look into this and have a patch with a somewhat different approach than the other patches. I took @tim.plunkett's idea of looking into overriding the init() function.

tim.plunkett’s picture

Seems to be a lot of duplication of the parent implementation. Is it possible to still call parent::init() and add in just the LB specific code?

danflanagan8’s picture

Yeah, that would be a good idea. Let's see if all the tests pass. If they do I'll post an updated patch with less duplicated code.

danflanagan8’s picture

Two failed tests. The one that's in Layout Builder is an easy fix, but I think the failed test in Umami indicates my approach is no good. The new init() function moves the links extra field from hidden to content (like it does with all extra fields), causing the test on umami config to fail.

I kind of liked overriding since it didn't require changes to any other functions, but I think now that the best approach will be to make changes to the getComponent() function, as was done in the patches prior to #33.

danflanagan8’s picture

Here's yet another attempt. This patch is a lot like the one in #30 but with the comments of #31 taken into account. This patch does not make any changes to preSave(). The changes to getComponent() and getSectionComponentForFieldName() are hopefully just a little bit clearer. I added a helper function to EntityDisplayBase in an attempt to keep things as clean as possible.

danflanagan8’s picture

Status: Needs work » Needs review
danflanagan8’s picture

FileSize
2.38 KB

I started feeling like #37 contained some overkill. This new patch is basically the patch from #12 plus the test. I think @waspper had it right from the start.

Also, I never addressed this comment:

Can we possibly change ExtraFieldBlock to not need this special casing?

I think the only way to avoid special casing in getComponent() is to add something like 'formatter' => TRUE as default configuration for extra field blocks. That's pretty hacky though.

danflanagan8’s picture

tim.plunkett’s picture

  1. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -479,6 +479,10 @@ public function getComponent($name) {
    +          return TRUE;
    

    We can't return a boolean here. The valid return types are an array or NULL. I think adding ['formatter' => []] to ExtraFieldBlock is a pretty good idea (instead of TRUE)

  2. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -535,7 +539,7 @@ private function getSectionComponentForFieldName($field_name) {
    +        if ($plugin instanceof DerivativeInspectionInterface && in_array($plugin->getBaseId(),['field_block', 'extra_field_block'])) {
    

    Missing space between , and [

    Also please add TRUE as the 3rd param to in_array

danflanagan8’s picture

@tim.plunkett

I think adding ['formatter' => []] to ExtraFieldBlock is a pretty good idea (instead of TRUE)

I'm not sure that and empty array would work because we typically see expressions like the following in hook_node_view to handle extra fields:

function layout_builder_test_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('layout_builder_test')) {
     // Do something
  }
}

If 'formatter' is set to an empty array, which is falsey, the Do something won't happen. Is there something truthy we could pick that isn't as hacky-looking as TRUE?

danflanagan8’s picture

Status: Needs review » Needs work
FileSize
4.19 KB
2.12 KB

Let's try a new patch where we set 'formatter' in the extra field block to some essentially empty but not falsey array. I wouldn't be surprised to see some failed tests resulting from this change. We'll see.

tim.plunkett’s picture

This is looking really good!
Couple points of feedback.

  1. +++ b/core/modules/layout_builder/src/Entity/LayoutBuilderEntityViewDisplay.php
    @@ -535,7 +535,7 @@ private function getSectionComponentForFieldName($field_name) {
    +        if ($plugin instanceof DerivativeInspectionInterface && in_array($plugin->getBaseId(),['field_block', 'extra_field_block'], TRUE)) {
    

    Still missing a space after the comma here

  2. +++ b/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php
    @@ -85,6 +85,12 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
    +      'formatter' => [
    +        'label' => NULL,
    +        'type' => NULL,
    +        'settings' => [],
    +        'third_party_settings' => [],
    +      ],
    

    According to EntityDisplayBase::setComponent() this is the correct fix, but only for settings/third_party_settings. Leave out label/type

  3. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
    @@ -887,6 +887,24 @@ public function testExtraFields() {
    +    // Consider extra field that is hidden by default. See Issue #3069578.
    +    // First make sure it's not displayed.
    

    Combine these two comments, and leave out the issue #.

  4. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
    @@ -887,6 +887,24 @@ public function testExtraFields() {
    +    // View the layout and try to add the extra field that is not visible by default.
    

    Remove "try to" from this sentence

  5. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
    @@ -887,6 +887,24 @@ public function testExtraFields() {
    +    $this->drupalGet("admin/structure/types/manage/bundle_with_section_field/display/default/layout");
    

    Nit: swap those " for '

ayushmishra206’s picture

Assigned: Unassigned » ayushmishra206
ayushmishra206’s picture

Assigned: ayushmishra206 » Unassigned
Status: Needs work » Needs review
FileSize
2.93 KB
4.1 KB

Made the changes requested in #44. Please review.

danflanagan8’s picture

Status: Needs review » Reviewed & tested by the community

Looks like #46 addresses all the concerns from #44. I'll set this RTBC.

tim.plunkett’s picture

In general, you shouldn't RTBC an issue you wrote patches for.
In this case, I was about to RTBC anyway, so it's not a problem.

Thanks for your work on this!

danflanagan8’s picture

Right, I guess I should recuse myself in such situations!

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 46: 3069578-46.patch, failed testing. View results

tim.plunkett’s picture

Status: Needs work » Reviewed & tested by the community

Drupal\Tests\ckeditor\FunctionalJavascript\CKEditorIntegrationTest is an unrelated random failure. Resetting to RTBC.

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/modules/layout_builder/src/Plugin/Block/ExtraFieldBlock.php
    @@ -85,6 +85,10 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
    +      'formatter' => [
    +        'settings' => [],
    +        'third_party_settings' => [],
    +      ],
    

    Should there be a config-schema change to go with this - block default configuration normally maps 1:1 to a schema entry

  2. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderTest.php
    @@ -887,6 +887,23 @@ public function testExtraFields() {
    +    // Consider extra field that is hidden by default, make sure it's not displayed.
    

    nit: more than 80 chars here

tim.plunkett’s picture

Ah yes, block.settings.field_block:*:*:* should be duplicated exact as-is but as block.settings.extra_field_block:*:*:*

@danflanagan8, can you do that so that I can reRTBC?

danflanagan8’s picture

There ya go. I also shortened the comment called out in #52.

tim.plunkett’s picture

Status: Needs review » Reviewed & tested by the community

Thanks! I think that suffices.

  • catch committed b94f170 on 9.1.x
    Issue #3069578 by danflanagan8, YurkinPark, ayushmishra206, andersen_ti...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed b94f170 and pushed to 9.1.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

Anybody’s picture

Hi @tim.plunkett and @catch. as modules like extra_field (see related issues) depend on this fix to work in layout_builder, I'd like to ask if you see a chance to backport these important fixes to 8.x to allow them to work as expected?

PCate’s picture

+1 for a backport of this to 8.x. Without this patch the Toc.js node field does not render.

The #54 patch applied cleanly and fixes the issue with 8.9.10 so I don't think a backport will need any modification to the patch.

yktdan’s picture

This is still here in D9.2. When I add a field to a content type that has been configured in layout mode, the field does not appear in the layout. As above, if you get out of layout mode and go to manage fields, the field is there but disabled. If you move it to enabled and reenable layout mode it now appears, but you have lost all the layout customization in the process.

danflanagan8’s picture

Hi @yktdan
I'm confident that this issue is resolved, but the issue summary is not very clear. This issue is specifically about "extra fields" that are not defined with 'visible' => TRUE in hook_extra_field_info. These field were previously not renderable by LB until they were moved out of the "hidden" region in Field UI.

Is this the problem you are having?

It looks to me like you are dealing with something that may be unexpected and annoying but not a bug. If you have a node with Layout overrides (like it's customized beyond the default layout), then it no longer picks up new changes that are made to the default layout. Is that what you're running into?

yktdan’s picture

Yes, I think that describes my issue.