Problem/Motivation

Currently all the field blocks in layout builder are being rendered in ---custom view modes. Having field templates for user defined view modes is not possible at the moment, and hence not able to get the required markup for the page when using layout builder.

This is due to usage of \Drupal\Core\Entity\EntityDisplayBase::CUSTOM_MODE in \Drupal\layout_builder\Plugin\Block\FieldBlock::getFormatter()

Proposed resolution

Force the field blocks to render with the view mode template suggestion that is used at the Layout Builder level

Remaining tasks

Decide if Layout Builder should provide an additional suggestion or just expose the info

User interface changes

N/A

API changes

N/A

Data model changes

N/A

CommentFileSizeAuthor
#63 3001313--63.patch1.01 KBrlmumford
#57 3001313-56.patch20.89 KBlostkangaroo
#57 interdiff-3001313-41-56.txt910 byteslostkangaroo
#56 3001313-56.patch41.79 KBlostkangaroo
#56 interdiff-3001313-41-56.txt1.78 KBlostkangaroo
#41 interdiff-3001313-34-41.txt846 bytesyogeshmpawar
#41 3001313-41.patch20.87 KByogeshmpawar
#34 3001313-34.patch20.87 KBbnjmnm
#34 interdiff_32-34.txt1.82 KBbnjmnm
#32 3001313-32.patch20.09 KBbnjmnm
#32 interdiff_29-32.txt4.43 KBbnjmnm
#29 3001313--29.patch19.78 KBbnjmnm
#29 interdiff_27-29.txt5.74 KBbnjmnm
#29 3001313-29-TESTS-ONLY.patch13.71 KBbnjmnm
#27 3001313-suggestions-27.patch19.7 KBbnjmnm
#27 interdiff_19--27.txt7.99 KBbnjmnm
#21 interdiff.3001313.17-21.txt1.71 KBCyberschorsch
#19 3001313-suggestions-19.patch11.65 KBCyberschorsch
#17 3001313-suggestions-17.patch11.87 KBbobbygryzynger
#16 3001313-suggestions-16-interdiff.txt23.1 KBbobbygryzynger
#16 3001313-suggestions-16.patch11.72 KBbobbygryzynger
#13 3001313-suggestions-13-interdiff.txt1.96 KBtim.plunkett
#13 3001313-suggestions-13.patch15.28 KBtim.plunkett
#9 3001313-suggestions-9.patch14.24 KBtim.plunkett
#8 view-mode-secondary.png70.75 KBhershey.k
#8 view-mode-full.png68.1 KBhershey.k
#2 Screen Shot 2018-09-18 at 12.16.07 PM.png420.13 KBmikey en
screenshot.png742.13 KBmikey en
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mikey en created an issue. See original summary.

mikey en’s picture

FileSize
420.13 KB
mikey en’s picture

Title: All field blocks in the layout builder do not have view mode suggestions » Field blocks in the layout builder do not have view mode suggestions
tim.plunkett’s picture

Category: Feature request » Bug report
Issue summary: View changes
Issue tags: +Blocks-Layouts, +Needs tests

Thanks for opening the issue! I think we can categorize this as a bug, as it was an oversight when writing the module.

tim.plunkett’s picture

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

Do you have a custom hook_theme_suggestions_alter() in a module or theme?
Because when I inspect the template suggestions I do not see one for the view mode at all:

<!-- FILE NAME SUGGESTIONS:
   * field--node--body--article.html.twig
   * field--node--body.html.twig
   * field--node--article.html.twig
   * field--body.html.twig
   x field--text-with-summary.html.twig
   * field.html.twig
-->
mikey en’s picture

Yes i do !, i uploaded the picture , it got hidden, sorry about that.

tim.plunkett’s picture

hershey.k’s picture

I've applied the latest patch from the referenced related issue and I can confirm that this is still an issue.

Field blocks displayed in different view modes in layout builder all reference a `_custom` view mode inside the $vars['element']['#view_mode'] value. Attempting to create a custom hook suggestions for field_blocks per the host entities view mode(s), something like below inside a hook_suggestions_alter() produces the attached results.

For a use case example: I have a field_block_node_title being printed on the page twice with two different view modes. One for the current nodes title (full view mode). A secondary for the `related content` title (secondary view mode). At the moment there is no way to control a separate theming template, from the field or block level per content (entity) view mode.

function hook_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($variables['theme_hook_original'] === 'field') {
    $element = $variables['element'];
    $suggestions[] = $variables['theme_hook_original'] . '__' . $element['#entity_type'] . '__' . $element['#field_name'] . '__' . $element['#view_mode'];
  }
}

view mode 1
view mode 2

tim.plunkett’s picture

Issue summary: View changes
Status: Active » Needs review
FileSize
14.24 KB

Still needs tests.
And a decision on whether to add this suggestion from within Layout Builder, or just stop short at making it possible to add.

As seen in the patch, this adds the correct information at

$element['#third_party_settings']['layout_builder']['view_mode']

I don't think it is possible to change the actual $element['#view_mode'] key. _custom is technically the correct value at that point, it's just that this is a nested rendering situation...

This issue needs at least two issues opened as blockers: one for the change to FormatterBase, one for ContextHandler.

tim.plunkett’s picture

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

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

fenstrat’s picture

Having the view mode suggestion in there seems like a pretty common use case. So I think this make sense to provide as a suggestion from layout builder, rather than just making it possible by placing it in #third_party_settings.

tim.plunkett’s picture

Fair point. This is still blocked by (and includes) those two issues (one RTBC, the other needs tests)

Status: Needs review » Needs work

The last submitted patch, 13: 3001313-suggestions-13.patch, failed testing. View results

tim.plunkett’s picture

Status: Needs work » Postponed
bobbygryzynger’s picture

Reroll against 8.7.x-dev. It looks like several things added in #13 were committed elsewhere.

bobbygryzynger’s picture

Cyberschorsch’s picture

#17 sort of works but there is an issue with actually using the suggestions. The reason is that the suggestions get added to the template suggestions before the system suggestions and will be placed at the bottom of all suggestions.

There are two solutions:
1) Change the module weight of layout_builder so the hook will be executed after the system module
2) Change the hook to hook_theme_suggestions_alter
3) Use hook_module_implements_alter to reorder the modules

Cyberschorsch’s picture

I discovered another issue with adding the view mode as context. The module "layout_library" can create layouts without having a view mode as display context. Since we do not provide a default view mode when creating a field block and the context is required, this will break.

I went ahead and added changes from #18 and from this comment to patch #17.

Status: Needs review » Needs work

The last submitted patch, 19: 3001313-suggestions-19.patch, failed testing. View results

Cyberschorsch’s picture

FileSize
1.71 KB

Adding missing interdiff

Petr Illek’s picture

I've give it a try (patch from #19 with interdiff from #21) and it is working for me, providing me with "field--node--title--page--teaser.html.twig" suggestion. That what I was looking after.

Petr Illek’s picture

Still working fine after update to 8.7.1.

AaronMcHale’s picture

Can confirm, worked for me

tim.plunkett’s picture

Assigned: Unassigned » tim.plunkett

Working on this

bnjmnm’s picture

Assigned: tim.plunkett » bnjmnm
bnjmnm’s picture

Assigned: bnjmnm » Unassigned
Status: Needs work » Needs review
FileSize
7.99 KB
19.7 KB

About this patch

  1. Addressed test failures in earlier patches by updating LayoutEntityHelperTrait::getSectionStorageForEntity to return a view mode context for every condition. Without this, inline blocks added to layout defaults were not being saved as block content entities, only serialized in config.
  2. View mode was appearing in the block add/config form. I opted to address this in the $form build, rather than making the view mode context required. When I tried the approach of making the view mode context required, FieldBlockTest would fail due to the deriver added in the layout_builder_fieldblock_test module, which in turn suggested making it required could potentially create problems for contrib modules. I think this will be a more easily managed solution unless there are specific reasons why the required-context approach should be used over doing it via $form.
  3. Added a functional test to confirm that view mode specific templates will be used when present. It seems like there's already sufficient kernel/unit coverage, but not sure enough to remove the "Needs tests" tag.
tim.plunkett’s picture

Issue tags: -Needs tests

Thanks for picking this up!

  1. +++ b/core/lib/Drupal/Core/Field/FormatterBase.php
    @@ -100,7 +100,7 @@ public function view(FieldItemListInterface $items, $langcode = NULL) {
    -        '#third_party_settings' => $this->getThirdPartySettings(),
    +        '#third_party_settings' => $this->thirdPartySettings,
    

    I think this is an unintentional revert introduced by a bad reroll, may have been my fault

  2. +++ b/core/modules/layout_builder/src/Context/LayoutBuilderContextTrait.php
    @@ -47,6 +49,13 @@ protected function getAvailableContexts(SectionStorageInterface $section_storage
    +    // In some instances, such as the layout_library module, view_mode is not
    +    // an available context, despite being required. If view_mode has no value,
    +    // set it to 'default'.
    +    if (!isset($contexts['view_mode']) || !$contexts['view_mode']->getContextValue()) {
    +      $contexts['view_mode'] = new Context(new ContextDefinition('string'), 'default');
    
    +++ b/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php
    @@ -123,6 +124,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
    +            'view_mode' => new ContextDefinition('string', 'View Mode', FALSE, FALSE, NULL, 'default'),
    

    Why doesn't the default value passed here satisfy this?

    Also this should switch to (new ContextDefinition('string'))->setDefaultValue('default'), to sidestep all those other params

  3. +++ b/core/modules/layout_builder/src/Plugin/SectionStorage/DefaultsSectionStorage.php
    @@ -33,6 +34,7 @@
    + *     "view_mode" = @ContextDefinition("string"),
    

    Ah, maybe this is the part that needs to change. This can be @ContextDefinition("string", default_value = "default"),

  4. +++ b/core/modules/layout_builder/tests/modules/layout_builder_field_block_theme_suggestions_test/layout_builder_field_block_theme_suggestions_test.module
    @@ -0,0 +1,17 @@
    +function layout_builder_field_block_theme_suggestions_test_theme() {
    +  return [
    +    'field__node__body__bundle_with_section_field__default' => [
    +      'base hook' => 'field',
    

    Not 100% clear to me why this is needed, don't the template suggestions handle this for you?

Along with the next patch, can you include a failing patch with just the functional test? Thanks!

bnjmnm’s picture

#28.1 -- fixed
#28 2/3 setting the default value in the annotation for DefaultsSectionStorage removed the need to set a default value in the deriver. I also figured out a way to get FieldBlockTest to work while making the deriver's view_mode required. This was accomplished by adding a ContextProvider service to layout_builder_fieldblock_test
#4

Not 100% clear to me why this is needed, don't the template suggestions handle this for you?

. If the template was provided in a theme, it would automatically be discovered based on filename and directly placement. As far as I know, Drupal will not know to look in the templates directory of a module without an implementation of hook_theme(). There may be a more elegant way to do it, but it doesn't automatically check the contents of the templates dir like it would in a theme.

tim.plunkett’s picture

Awesome, thanks!

  1. +++ b/core/modules/layout_builder/src/Context/LayoutBuilderContextTrait.php
    @@ -47,6 +49,13 @@ protected function getAvailableContexts(SectionStorageInterface $section_storage
    +    // In some instances, such as the layout_library module, view_mode is not
    +    // an available context, despite being required. If view_mode has no value,
    +    // set it to 'default'.
    +    if (!isset($contexts['view_mode']) || !$contexts['view_mode']->getContextValue()) {
    +      $contexts['view_mode'] = new Context(new ContextDefinition('string'), 'default');
    +    }
    

    Idk if I highlighted this hunk as well above, but this seems like another instance of passing `default` that seems like it's in the wrong place

  2. +++ b/core/modules/layout_builder/src/Plugin/Derivative/FieldBlockDeriver.php
    @@ -123,6 +124,7 @@ public function getDerivativeDefinitions($base_plugin_definition) {
    +            'view_mode' => (new ContextDefinition('string')),
    

    If there's no method call on the new object, then you don't need the extra ()

  3. +++ b/core/modules/layout_builder/tests/modules/layout_builder_field_block_theme_suggestions_test/layout_builder_field_block_theme_suggestions_test.module
    @@ -0,0 +1,17 @@
    +function layout_builder_field_block_theme_suggestions_test_theme() {
    

    Thanks for clarifying this, can you put an inline comment that says "this is only needed because it's a module, not a theme"?

The last submitted patch, 29: 3001313-29-TESTS-ONLY.patch, failed testing. View results

bnjmnm’s picture

#30.1

this seems like another instance of passing `default` that seems like it's in the wrong place

I moved this to what seems like a more appropriate place Drupal\layout_builder\Plugin\SectionStorage\SectionStorageBase::getContextsFromPreview() and revised the content to better explain what is being addressed. Interested to know if there's a better way to go about this - the problem this addresses can be reproduced by installing Layout Library and visiting an "Edit Layout" page. They Layout library SectionStorage has its own getContextsDuringPreview() method that does not return view_mode and there is not a default defined. Perhaps this is something that could be implemented with a deprecation path but I'm not entirely sure how that would be done.

#30.2 Unnecessary parentheses removed.

#30.3 added some clarification to the hook_theme() implementation

Status: Needs review » Needs work

The last submitted patch, 32: 3001313-32.patch, failed testing. View results

bnjmnm’s picture

Status: Needs work » Needs review
FileSize
1.82 KB
20.87 KB

The test failure in #32 was due to OverridesSectionStorage having a view mode context without a default value (which surfaced due to adding a check for view mode in Drupal\layout_builder\Plugin\SectionStorage\SectionStorageBase::getContextsFromPreview()

Although this was addressed by updating OverridesSectionStorage to have a default value in the view mode context, I also added a validation condition inside the getContextsFromPreview() conditional that checks for a view mode context, so it does not break contrib modules with SectionStorage plugins that have view mode contexts without default values.

jonraedeke’s picture

This patch doesn't seem to work for me. Here's what I get for the body field placed via Layout builder:

<!-- FILE NAME SUGGESTIONS:
   * field--node--body--page.html.twig
   * field--node--body.html.twig
   * field--node--page.html.twig
   x field--body.html.twig
   * field--text-with-summary.html.twig
   * field.html.twig
-->

When I try to add a suggestion for view_mode, like this:

function hook_theme_suggestions_field_alter(array &$suggestions, array $variables) {
  $element = $variables['element'];
  $field_name = $element['#field_name'];
  $view_mode = $element['#view_mode'];
  $suggestions[] = 'field__' . $field_name . '__' . $view_mode;
}

I get these suggestions:

<!-- FILE NAME SUGGESTIONS:
   * field--body--layout-builder-full-0-7fa9615d-fe2f-4f85-92d2-5e5743e0e5a8-799451-7bae016a755459cba0f1ba2743f6121012bc338e1840a40d8f1791bc3aac218c.html.twig
   * field--node--body--page.html.twig
   * field--node--body.html.twig
   * field--node--page.html.twig
   x field--body.html.twig
   * field--text-with-summary.html.twig
   * field.html.twig
-->
tim.plunkett’s picture

$element['#view_mode']; is not changed in this issue. It will function exactly that way with and without the path.

As shown in the patch, it is using $element['#third_party_settings']['layout_builder']['view_mode']

Curious that with the latest patch, layout_builder_theme_suggestions_field_alter() isn't handling it for you. It should be.

jonraedeke’s picture

Apologies, I was not using the latest version of core. The template suggestion with view mode appears now without the need to use a hook. Thanks for all the work here!

<!-- FILE NAME SUGGESTIONS:
   * field--node--body--page--full.html.twig
   * field--node--body--page.html.twig
   * field--node--body.html.twig
   * field--node--page.html.twig
   x field--body.html.twig
   * field--text-with-summary.html.twig
   * field.html.twig
-->

If a themer adds suggestions for fields with view mode added without layout builder, there is still an extraneous entry for layout builder added fields. Maybe that could be unset?

When I try to add a suggestion with view_mode for fields added displayed without Layout Builder, like this:

function hook_theme_suggestions_field_alter(array &$suggestions, array $variables) {
  $element = $variables['element'];
  $field_name = $element['#field_name'];
  $view_mode = $element['#view_mode'];
  $suggestions[] = 'field__' . $field_name . '__' . $view_mode;
}

For a field added with Layout builder I then get:

<!-- FILE NAME SUGGESTIONS:
   * field--body--layout-builder-full-0-7fa9615d-fe2f-4f85-92d2-5e5743e0e5a8-799451-7bae016a755459cba0f1ba2743f6121012bc338e1840a40d8f1791bc3aac218c.html.twig
   * field--node--body--page--full.html.twig
   * field--node--body--page.html.twig
   * field--node--body.html.twig
   * field--node--page.html.twig
   x field--body.html.twig
   * field--text-with-summary.html.twig
   * field.html.twig
-->
tim.plunkett’s picture

That additional one with all the UUIDs is from the Quick Edit module integration. It can be ignored.

borisson_’s picture

Status: Needs review » Needs work

I only found 2 really small nitpicks that are related to the coding standards. Otherwise I don't see anything with this patch that could be improved.

  1. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderFieldBlockThemeSuggestionsTest.php
    @@ -0,0 +1,68 @@
    +class LayoutBuilderFieldBlockThemeSuggestionsTest extends BrowserTestBase {
    +  /**
    

    neeeds addtional newline.

  2. +++ b/core/modules/layout_builder/tests/src/Functional/LayoutBuilderFieldBlockThemeSuggestionsTest.php
    @@ -0,0 +1,68 @@
    +
    +  }
    

    I think this blank line can go. But I am not sure if we have a PHPCS rule for it.

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
FileSize
20.87 KB
846 bytes

Comments addressed in #39 & added an interdiff as well.

borisson_’s picture

Status: Needs review » Reviewed & tested by the community

My nitpicks have been resolved, this looks good overall.

tim.plunkett’s picture

I concur that this is ready to go. Thanks everyone!

matt_paz’s picture

Status: Reviewed & tested by the community » Needs review

Hmm. It seems I must have misattributed this patch as the source of issues in #3063081.

matt_paz’s picture

Status: Needs review » Reviewed & tested by the community

Restoring status after recognizing my error.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 41: 3001313-41.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Reviewed & tested by the community

I think that test failure is unrelated as it was in a media js-test.

larowlan’s picture

issue credits

  • larowlan committed 90534ac on 8.8.x
    Issue #3001313 by bnjmnm, tim.plunkett, bobbygryzynger, Cyberschorsch,...
larowlan’s picture

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

Committed 90534ac and pushed to 8.8.x. Thanks!

I'm of the opinion that this is not eligble for back-port to 8.7.x because it could have unintended consequences to templates/markup - see allowed changes - but its a grey area so I'll put it to a poll of other committers

larowlan’s picture

I realise this has already gone into 8.8 - but could I request a posthumous change record, it would help with the decision around backporting.

tim.plunkett’s picture

This doesn't work on 8.7 because #3029627: FormatterBase should pass along third party settings wasn't backported. Reopened that one

annisar’s picture

Can confirm when using both the patches , https://www.drupal.org/files/issues/2019-06-17/3001313-41.patch and https://www.drupal.org/files/issues/2019-04-12/3029627-tps-10.patch works in 8.7x for generating the view mode suggestions !!

larowlan’s picture

Can we get a change notice here, if this is to be backported, we need to let people know - thanks

larowlan’s picture

Status: Reviewed & tested by the community » Needs review
Issue tags: +Needs change record

For #54

lostkangaroo’s picture

Using the patch in #41 was still allowing failures of view_mode context using 8.7.x. This updates #41 to ensure a default value when getting derivative definitions.

lostkangaroo’s picture

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

Drupal 8.7.9 was released on November 6 and is the final full bugfix release for the Drupal 8.7.x series. Drupal 8.7.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.8.0 on December 4, 2019. (Drupal 8.8.0-beta1 is available for testing.)

Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.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.

Anybody’s picture

Version: 8.8.x-dev » 8.9.x-dev
Anybody’s picture

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

SORRY - my stupid mistake, I didn't see this was already committed and you were just discussing the backport to 8.7.x!

Now where 8.8.0 is out - should we close this FIXED?

tim.plunkett’s picture

Version: 8.7.x-dev » 8.8.x-dev
Status: Needs review » Fixed
Issue tags: -Needs change record

Agreed.

rlmumford’s picture

This fix is causing problems for users of the mini_layouts module - hopefully someone can offer some advice.

https://www.drupal.org/project/mini_layouts/issues/3110850
https://www.drupal.org/project/mini_layouts/issues/3112090

People often create mini layouts with a required context or two and then use FieldBlocks to render fields. These mini layouts can then be placed as a block anywhere else. This fix has caused all of those mini_layouts to throw fatal errors because the 'view_mode' context is not satisfied.

I can't work out what the appropriate way forward is - do mini layouts users have to define two required contexts for each entity they're using in their mini layout? That seems like an uncomfortable burden to place on the users. Can we make it so that, if there isn't a view_mode context, the default view mode (or even we revert to the 'custom' behaviour as before!) is used rather than throwing an error?

rlmumford’s picture

I know this patch will probably need a seperate issue to get committed, but I think this is probably all it needs to avoid breaking old mini_layouts. Just set the default value of the context definition to 'default'.

Status: Fixed » Closed (fixed)

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