Problem/Motivation

#2171269: Handle block rendering's #attributes correctly (fixes in-place editing of custom blocks) introduced a change where if a block's content render array contained #attributes, then those attributes would be merged into the block wrapper's attributes. This is improper for certain use cases such as forms in blocks where the attributes belong on the content's <form> element, not the wrapper.

For example a if a block returns something like this:

array(
  '#attributes' => array(
    'class' => array(
      'foo-bar'
    ),
    'data-test' => 'This is just a test'
  ),
  '#markup' => 'This is block content'
);

The rendered HTML will be:

<div id="block-foobartest" class="foo-bar" data-test="This is just a test">
  This is block content.
</div>

instead of:

<div id="block-foobartest">
  <div class="content foo-bar" data-test="This is just a test">
    This is block content.
  </div>
</div>

Steps to reproduce

From #10:

  • Install the Standard profile.
  • Add the Search Form block to a region on the page, somewhere it isn't likely to be given special theming. It's already in the Secondary Menu and while it does exhibit the bug there it's harder to tell due to alterations that are made.
  • Visit the site front page.
  • Inspect the block's HTML.

Expected result

The form contained in the block should have the attribute drupal-data-selector="search-block-form-###".

Actual result

The block wrapping the form has the expected attribute.

Proposed resolution

Update BlockViewBuilder so that it applies the #wrapper_attributes from a block's content render array to the outer block wrapper instead of the content's #attributes.

Remaining tasks

  • Subsystem maintainer approval Given in #17
  • Make certain this change doesn't break anything else.
  • Review

User interface changes

It's possible that themes could rely on the attributes that are being merged into the wrapper. The change might break CSS or JS that are selecting based on an attribute.

Introduced terminology

API changes

Data model changes

Release notes snippet

Issue fork drupal-2486267

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

Anonymous’s picture

Issue summary: View changes
joelpittet’s picture

Component: render system » theme system
Status: Active » Closed (works as designed)
Issue tags: +Twig

This is by design. If you are using bartik theme's templates you can pass in #content_attributes like what D7 had. We decided to remove some divs.

Anonymous’s picture

Status: Closed (works as designed) » Active

I understand the simplifying of D8's markup. but that is not what I have issue with.
My issues is that a block is providing a piece of content, which is a "unit" of content on its own, and should be immutable in a way. But the render engine will break this unit into pieces(ie. the render array) and it will steal attributes out of it and pass it to the block itself rendering the original "unit" of content improperly.

joelpittet’s picture

Ah did a bit of research and see kinda what you are trying to explain. There is a specific comment to that effect.

core/modules/block/src/BlockViewBuilder.php:212

      // Place the $content returned by the block plugin into a 'content' child
      // element, as a way to allow the plugin to have complete control of its
      // properties and rendering (e.g., its own #theme) without conflicting
      // with the properties used above, or alternate ones used by alternate
      // block rendering approaches in contrib (e.g., Panels). However, the use
      // of a child element is an implementation detail of this particular block
      // rendering approach. Semantically, the content returned by the plugin
      // "is the" block, and in particular, #attributes and #contextual_links is
      // information about the *entire* block. Therefore, we must move these
      // properties from $content and merge them into the top-level element.

I think you are write and we really should have been using #wrapper_attributes, to effect that outer element from our block plugin build() render arrary I think.

Am I following you @ivanjaros?

joelpittet’s picture

Status: Active » Needs review
StatusFileSize
new1.13 KB

Here's a quick patch to see how many test fail.

There is also a good chance this won't get into release considering it's next week. Don't want to get your hopes up @ivanjaros.

Status: Needs review » Needs work

The last submitted patch, 5: attributes_of_a_block-2486267-5-boom.patch, failed testing.

Anonymous’s picture

Yes, usage of #wrapper_attributes makes much more sense.

joelpittet’s picture

Let's see if a framework manager can chime in here.

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.

effulgentsia’s picture

Version: 8.1.x-dev » 8.2.x-dev
Component: theme system » block.module
Issue tags: -Needs framework manager review +Needs subsystem maintainer review
Related issues: +#2171269: Handle block rendering's #attributes correctly (fixes in-place editing of custom blocks)
StatusFileSize
new49.58 KB

This is especially bad for blocks that represent forms since none of the form attributes is preserved.

I was curious how this affected SearchBlock, and found that most form attributes, such as method and action are ok, because they're stored as #method and #action on the render array, rather than in #attributes. However, I did find that in HEAD, $form['#attributes']['data-drupal-selector'] ends up getting moved from the <form> tag to the block's <div> wrapper, per the attached screenshot.

The code in #4 was introduced in #2171269: Handle block rendering's #attributes correctly (fixes in-place editing of custom blocks), so adding it as a related issue, and I'll post a comment there asking for people who worked on that to comment here.

Prior to giving framework manager review on this, I'd like input from block.module maintainers, so tagging for that.

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

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now 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.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now 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.

tisteegz’s picture

I am having this issue with trying to use theme item list. In my block class I have:

public function build() {

    return array(
      '#title' => 'Title',
      '#theme' => 'item_list',
      '#items' => $items,
      '#attributes' => array(
        'class' => array('class'),
      ),
    );
  }

Instead of the class feeding through to the list it is being applied to the block. I am unsure on how to get around this to instead have the class applied to the list instead of the block. Will give the patch above in #5 a go however I am now up to Drupal 8.3 so I don't know if it is still going to apply.

Anonymous’s picture

I think that you can wrap the array into an empty one and it should not bubble out but I'm not 100% sure.(return [[ ... ]]).

tisteegz’s picture

Ah thanks! That worked perfectly.

public function build() {
    return [[
      '#title' => 'Title',
      '#theme' => 'item_list',
      '#items' => $items,
      '#attributes' => array(
        'class' => array('class'),
      ),
    ]];
}

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

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now 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.

tim.plunkett’s picture

I agree this is a bug. And at first I wasn't sure how best to fix it without breaking BC.
Except that render arrays are exempted from the BC policy!

I think a switch to #wrapper_attributes would be good.

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

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now 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.

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

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now 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.

joum’s picture

Is anyone comfortable enough to provide a workaround for this while a fix isn't available?

I'm trying to add attributes to a form but they keep getting bubbled up to the block's div.

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.

martygraphie’s picture

Hello,
I notice that the problem is still present, I have partially taken over the joelpittet patch. The latter solves the problem well

martygraphie’s picture

StatusFileSize
new1.5 KB

Sorry the comment #22 doesn't have the right file, it's #23

martygraphie’s picture

Status: Needs work » Needs review

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.

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.

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.

akram zairig’s picture

I've encountered the same issue on Drupal 9.0.14
Is there any working patch on Drupal 9 ?

Taran2L made their first commit to this issue’s fork.

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.

johnjw59@gmail.com made their first commit to this issue’s fork.

johnjw59’s picture

Just pushed a new commit that applies the same fix to blocks placed via layout builder.

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.

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Bug Smash Initiative, +Needs tests

there doesn't appear to be anything to review the patch nor MR are passing tests.

And if this is a bug it will tests of it's own.

smustgrave’s picture

Status: Needs work » Postponed (maintainer needs more info)

Is this a twig issue? Tried the MR and patch which both applied cleanly to 9.5.x but didn't do anything with the rendering.

Also is it really a bug ?

Current olivero block twig

<div{{ attributes.addClass(classes) }}>
  {{ title_prefix }}
  {% if label %}
    <h2{{ title_attributes.addClass('block__title') }}>{{ label }}</h2>
  {% endif %}
  {{ title_suffix }}
  {% block content %}
    <div{{ content_attributes.addClass('block__content') }}>
      {{ content }}
    </div>
  {% endblock %}
</div>

To match change in description

<div id="{{ attributes.id }}">
  <div{{ attributes.addClass(classes)|without('id') }}>
    {{ title_prefix }}
    {% if label %}
      <h2{{ title_attributes.addClass('block__title') }}>{{ label }}</h2>
    {% endif %}
    {{ title_suffix }}
    {% block content %}
      <div{{ content_attributes.addClass('block__content') }}>
        {{ content }}
      </div>
    {% endblock %}
  </div>
</div>
taran2l’s picture

Status: Postponed (maintainer needs more info) » Needs work

This is not a twig issue, and everyone agreed that this is an issue. Not sure what else is needed.

smustgrave’s picture

Maybe I don't fully understand the rendering but to get the output mentioned in the description don't you need to wrap in an additional div.

In an example block I'm using this is my build array

    return [
      '#attributes' => array(
        'class' => array(
          'foo-bar'
        ),
        'data-test' => 'This is just a test'
      ),
      '#markup' => 'This is block content'
    ];

With or without the patch I'm seeing class, id, and data-test appear on the same div. So maybe this needs an issue summary update.

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.

scottsawyer’s picture

I am running into this problem with exposed forms in blocks, but it only surfaced when I updated to D 9.5. I was using views_block_filter_block because my views were block displays and I needed the exposed filters in separate blocks. It seems like the D9 update superseded views_block_filter_block, changing where the attributes were attached.

I patched with the MR, but it doesn't seem to be working, exposed form class attributes are still being moved to the containing block. If you have a custom block template for blocks containing views exposed forms that don't output all of the attributes, it breaks the ajax as well as the CSS in my case.

I worked around the issue by refactoring my template structure, I was fortunate to find a relatively simple solution, unfortunate that it cost me half a day to discover the problem and fix it.

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.

dcam changed the visibility of the branch 2486267-attributes-of-a to hidden.

dcam changed the visibility of the branch 11.x to hidden.

dcam’s picture

Issue summary: View changes
Issue tags: -Needs tests

Based on comment #10 I checked to see if this is still an issue in Drupal 11. It is. The same problem with the Search block form's data-drupal-selector attribute being applied to the block wrapper still exists.

There was no need to make a new test for this. The test created for the related original issue, #2171269: Handle block rendering's #attributes correctly (fixes in-place editing of custom blocks), can be adapted to check the change.

MR 1402 was broken. I don't know why some of the additional changes in it were made because they aren't well documented. The change from #atrributes to #wrapper_attributes was lost. I think that's the reason for the confusion in the more recent comments. I'm sure that it stopped doing anything to fix the issue. Since it's difficult or impossible to rebase MRs for old Core versions anyway, I hid the branch and created a new one for D11 restarting from the #5 patch. We'll see if this causes other tests to fail.

dcam’s picture

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

I didn't expect it to pass. I assumed that something else was probably relying on the attributes as they were. Oh well.

I made a change record: https://www.drupal.org/node/3525287.

dcam’s picture

StatusFileSize
new14.29 KB

I worked on this issue over the weekend not realizing that I'd experience it first-hand two days later. I've been adding inline styles to the .views-exposed-form class. Then I navigated to a different page where the exposed form is in a separate block. The class was bubbled up to the block wrapper, causing the block heading to be displayed in-line with the form as shown in the image below.

A demonstration of the block attribute bug where a form class bubbled up to the block wrapper

smustgrave’s picture

This seems like it could be an immediate breaking change if I had css written for before.

catch’s picture

I ran into this logic recently on another issue and the current behaviour is very confusing as #48 demonstrates. We can't assume that everything rendered via block module is never rendered in any other context - especially with layout builder / experience builder and etc.

smustgrave’s picture

If we aren’t concerned with #49 can add to my review list for tomorrow

dcam’s picture

I keep running into this error as I apply my new theme to more sites. But now I've had a WSoD crash because of it. I'm altering Views exposed forms to format them as USWDS Search components. It involves applying a few classes, changing the text input type to search, and setting role="search" on the form. For some reason, that last one, setting the role attribute, really caused a problem when the exposed form is in a block and that block has its title display on. template_preprocess_block() (this site is still in D10) tries to set a unique ID for the block with Html::getUniqueId(). When the role attribute is bubbled up to the block due to this issue, suddenly the preprocess function starts passing the title render array to getUniqueId(). Then the error is thrown because the expected input is a string, not an array.

I didn't bother trying to figure out what weird code path causes that to happen. I'm fortunate that I can simply turn the title display off in this one instance. I just want to point out that there are scenarios where this isn't harmless. I'm lucky that I knew about this issue so I could work out what was going on.

smustgrave’s picture

Status: Needs review » Needs work

Sorry to take so long, rebased the MR and it's got pipeline failures.

Feel free to ping me and I'll try and get to it sooner.

With regards to my concern if no one else has it I'll ignore it.

dcam’s picture

Status: Needs work » Needs review

I've seen that random Unit test error twice before on another issue. It's unrelated.

dcam’s picture

With regards to my concern if no one else has it I'll ignore it.

I'm biased because it's been directly impacting me. Maybe we need to tag it for framework or even release manager review.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs framework manager review

Going to mark as this does fix the issue. Will tag but weird case I'm not sure needs framework manager sign off or not.

catch’s picture

This needs frontend framework manager review rather than framework manager review.

If it was possible we'd probably want a bc layer for this in stable9 so that themes depending on that get attributes in the same way as they do now, but not sure how we'd implement that.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.

needs-review-queue-bot’s picture

Status: Reviewed & tested by the community » Needs work
StatusFileSize
new949 bytes

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Reviewed & tested by the community

Post-bot-rebellion rebase

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

#57 needs addressing we've still not had a frontend framework manager review and a bc layer in stable9 would be good. I think we have to be concerned about breaking existing sites here.

dcam’s picture

I added backward compatibility to stable9. I even added a basic test for it.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new1.3 KB

The Needs Review Queue Bot tested this issue. It fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.

dcam’s picture

Status: Needs work » Needs review
nod_’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs frontend framework manager review

That works for me, CR is ok too.

catch’s picture

Version: main » 11.x-dev
Status: Reviewed & tested by the community » Fixed

OK this was a very tricky issue, the bc layer in stable9 and sign-off from @nod_ makes me a lot happier about committing it, thanks for sticking with it for 11 years everyone.

Committed/pushed to main and cherry-picked to 11.x, thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

  • catch committed 4e58746c on 11.x
    fix: #2486267 Attributes of a block content are applied to block itself...

  • catch committed 701ea27c on main
    fix: #2486267 Attributes of a block content are applied to block itself...
quietone’s picture

Reword the CR to put the change first and publish.