Problem/Motivation

Updates from Drupal 9.2.10 to Drupal 9.3.0 are adding an --2 suffix to block-ID's (maybe only views-block-ID's?). For example block-views-block-newsslider-block-1 changes to block-views-block-newsslider-block-1--2, causing all JS an CSS selectors applied to the specific IDs not to work anymore and breaking the design of the website. This happens at least to all block-views-block-Elements of the affected websites.

This happend with different websites and different base themes (Classy, Bootstrap 3).

Setup:

Setup

Steps to reproduce

Update from Drupal 9.2.10 to Drupal 9.3.0

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

GOT intermedia created an issue. See original summary.

larowlan’s picture

Those IDs would always be volatile, you should use data attributes for JS and classes for css

ivo got’s picture

@larowlan Okay, thank you. We have been using ID's of blocks in CSS for years (since D6) in dozens of projects but this never happend before. Does this mean we hat a lot of luck or did something significant change in 9.3.0?

adrury’s picture

We are also seeing this. In our case, the suffix is only added to blocks when there is a logged in user. In a logged out state, the blocks get their expected identifiers.

We're working on updating our JS/CSS references as much as possible to not use the generated IDs. The problem we're running into is with ARIA - we have a search block that we show/hide when a toggle is activated. We were using the auto-generated id in aria-controls, but that obviously broke with this update, and I can't get any preprocess hooks or the Twig to give me the ID in time to shove it in the aria-controls I'm working around that now by adding a wrapper div around the block if there's content, but it feels icky.

    {% if elements.searchblock['#markup']|trim != '' %}
        <div id="search-container">
          {{ elements.searchblock }}
        </div>
      {% endif %}
larowlan’s picture

It would be good to track down the issue that caused this change

larowlan’s picture

I've added this to the 9.3.0 release notes as a Known issue until we work out what caused it

papagrande’s picture

I've seen that behavior for years since 8.x. I've never been able to track down the cause or recreate it consistently.

I know that's not much help, but perhaps 9.3 made it worse.

netsliver’s picture

same problem, beyond the IDs, this also poses a problem on the templates

container--webform-actions--webform-submission-s-inscrire-a-la-newsletter-add-form.html.twig becomes container--webform-actions--webform-submission-s-inscrire-a-la-newsletter-add-form--2.html.twig

changing everything is a real headache

netsliver’s picture

when I debug drupal seems to go 2 times in template_preprocess_block for blocks created by other modules

artis’s picture

I'm experiencing this also but only on one of the dozens of sites we manage. For us, it's limited only to Views blocks.

adrury’s picture

I can't add anything to the true source of the problem, but maybe this will help someone else to narrow down on the source: on further review, I think this is only happening for us on view blocks that have exposed forms when there is a logged in user.

netsliver’s picture

content blocks seems to be work, but problem with views blocks, webform blocks and probably others

kevin.pfeifer’s picture

As far as I have seen it that part of the block class is being generated by the machine name of that view block.
I would always recommend you to set custom/unqiue machine names for all view blocks and not keep the generic "block_1", "block_2" etc. machine name.
You can find the view blocks machine name in the view => Open "Advanced" Accordion on the right => "Other" Section first item is "Machine Name"
Just be aware that all references to that block will need to be redone (Blocklayout, Context or wherever) since that machine name is used to reference that view block.

Maybe Drupal has added a failback if 2 blocks have the same machine name (which shouldn't be possible at all but maybe) that "--2", "--3" etc. is being appended so its still unique.

ericmulder1980’s picture

Facing the same issue here with broken templates after updating to 9.3. In our case it is not the CSS but logic within TWIG templates that cease to work.

For example:

{% if attributes.id == 'block-searchfieldblock-2' %}

This no longer works because of the "--2" suffix now added twice. To make it work again i would have to use the following.

{% if attributes.id == 'block-searchfieldblock-2--2' %}

We use these checks in templates when a block is rendered multiple times on a page but needs some tweaks based on the context of where it is placed.

kevin.pfeifer’s picture

The only way how I can somewhat reproduce that on my bare 9.3 install is to insert the same view block into the block layout twice.
With that I now have

block-views-block-comments-recent-block-1
and
block-views-block-comments-recent-block-1-2

for a view block which has the machine name block_1

But I guess this is expected / not the problem here right now.

Would love to debug that but I would need a good description on how to reproduce that.

kallado’s picture

I got that behaviour in the blocks that contain forms (ex: Search and custom plugin Blocks) . I had to fix the css and js selectors in some cases, not something specially hard but it's tough if you have a lot of sites to manage. Even if you don't usually use this selector you will still fell forced to check them anyway.

JuankMG’s picture

We have the same issue in our case while user is loged in block's names are correct, If you check the site as anonimous user names add --2 It happens with blocks derivated from costum module. I have patched this on CSS file theme...

artis’s picture

I think this is caused by the block being pre-rendered somewhere to check if it's empty before output. Then it gets rendered a second time in the actual twig template or something similar. There is a longstanding issue with empty template regions printing since there wasn't always a way to know if a view would be empty or not. 9.3 must contain a supposed fix to that issue which causes this one.

In our case, I left the existing selectors in CSS and JS, but added an additional new selector with "--2" appended to protect against the possibility that this is all resolved someday and the selectors revert.

Going forward, I think @kevin.pfeifer has the best advice for site builders in comment #13 :

I would always recommend you to set custom/unqiue machine names for all view blocks and not keep the generic "block_1", "block_2" etc. machine name.
You can find the view blocks machine name in the view => Open "Advanced" Accordion on the right => "Other" Section first item is "Machine Name"
Just be aware that all references to that block will need to be redone (Blocklayout, Context or wherever) since that machine name is used to reference that view block.

noah’s picture

Priority: Normal » Major

We're seeing this with all blocks (not just Views blocks, also system blocks, etc.), and with other elements as well—forms at least, and I'm keeping my eyes open for more. It's a bit of a nightmare scenario for us, affecting tens of thousands of lines of CSS and JS for dozens of sites created over the past 6 years or so. I guess it's on me for not having known that HTML IDs weren't going to be reliable, but the fact that they were for years and now suddenly aren't is a bit of a gut punch.

I'm going bump the status up to "Major" in hopes that someone who really understands what's going on here will weigh in to at least explain definitively what causes it (and maybe even suggest a good workaround so that older sites don't break when updated to 9.3.x). In the meantime, in case this is useful to anyone else, I'm cautiously gradually adding this to custom themes to eliminate the "--X" appended to element IDs:

function [theme_name]_preprocess_block(&$variables) {
  if (isset($variables['attributes']) && (isset($variables['attributes']['id'])) && ($variables['attributes']['id'])) $variables['attributes']['id'] = _[theme_name]_clean_id($variables['attributes']['id']);
}
function [theme_name]_preprocess_form(&$variables) {
  if (isset($variables['attributes']) && (isset($variables['attributes']['id'])) && ($variables['attributes']['id'])) $variables['attributes']['id'] = _[theme_name]_clean_id($variables['attributes']['id']);
}
function _[theme_name]_clean_id($id) {
  $id_parts = explode('--', $id);
  if (count($id_parts) > 1) {
    $last_id_part = end($id_parts);
    if (ctype_digit($last_id_part)) $discard = array_pop($id_parts);
    $id = implode('--', $id_parts);
  }
  return $id;
}

Assuming this continues to work and not break anything, I'll just plan to add additional preprocess functions for any other elements I encounter that exhibit this behaviour. Of course, there may be circumstances where the "--X" is required to prevent duplicate HTML IDs on the same page, but for us at this point that's significantly less disruptive than large swaths of CSS and JS no longer referencing the right elements.

noah’s picture

One additional note re:

I would always recommend you to set custom/unqiue machine names for all view blocks and not keep the generic "block_1", "block_2" etc. machine name.

I 100% endorse this idea for other reasons, but it doesn't obviate this problem. I'm looking at an example of a "Events" Views block with ID "front_page_block" appearing with the HTML ID "block-views-block-events-front-page-block--2".

j-lee’s picture

Can confirm the issue with custom plugin Blocks as described at #16.
The blocks are placed only one time with unique names via the block layout.

goz’s picture

Assigned: Unassigned » goz

I have same issue with custom block placed only one time. The --2 suffix on id attributes reveals the block is generated twice, which is a regression from 9.3.X on 9.2.x.

Digging in this issue, i found that token generated by \Drupal\Core\Render\PlaceholderGenerator::createPlaceholder() is different on the second call.
Token should be the same at each call, which allow to use cache and not generate markup again.

Otherwise, $placeholder_render_array is different, so hash is different. In my case, the difference comes from contexts value.

During the first render :
s:8:"contexts";a:3:{i:0;s:28:"languages:language_interface";i:2;s:5:"theme";i:3;s:16:"user.permissions";}

During the second render :
s:8:"contexts";a:3:{i:0;s:28:"languages:language_interface";i:1;s:5:"theme";i:2;s:16:"user.permissions";}

To avoid this kind of issue, we should be sure keys, contexts and tags will always be generated in the same order, without missing keys in array keys.

goz’s picture

goz’s picture

Assigned: goz » Unassigned
Status: Active » Needs review
Issue tags: +Needs tests
StatusFileSize
new2.83 KB

Here is a patch to fix this.

Still needs tests to confirm issue and the fix.

goz’s picture

papagrande’s picture

A few small nits on first review:

  1. +++ b/core/lib/Drupal/Core/Render/PlaceholderGenerator.php
    @@ -77,6 +77,16 @@ public function createPlaceholder(array $element) {
    +    // making hash. Issue #3225328 remove sort from contexts and tags arrays for
    

    Should be "removes"

  2. +++ b/core/modules/big_pipe/src/Render/Placeholder/BigPipeStrategy.php
    @@ -274,6 +274,16 @@ protected static function generateBigPipePlaceholderId($original_placeholder, ar
    +      // making hash. Issue #3225328 remove sort from contexts and tags arrays for
    

    Should be "removes" and the line needs to be less than 80 characters.

scultetus’s picture

I have the same problem with Drupal 9.3.2 suffixing elements with "--2". I identified the problem in blocks, forms and form elements. All encoding using ID's is compromised. Its a big problem!

goz’s picture

I'm not sure what is the best way to test this.

1/ Create a block and confirm id is suffixed by --2 : It's closed from the issue, and how we discover it. Maybe it could fail in the future if create placeholder generate different hash when should not. But test is more heavy to build and run.

2/ Since i found the issue comes from sorting context/tags cache array, mock element with contexts/tags sorted differently and only check createPlaceholder return the same result : Tests only the solution. Lighter but only tests the sort contexts/tags issue wen generating hash placeholder. Doesn't cover other similar issues hashing render array.

goz’s picture

Component: block.module » render system

Move this issue to render system component since it's not only blocks by also forms or every renderable array generated by lazy_builder/placeholder.

goz’s picture

I fix comments from #26

I add tests.

*-tests-only.patch file should fail, the purpose of this patch is to add tests to show current code issue.

coretex’s picture

Thank you Goz for the patch. The patch in #30 fixes the issue on our websites.

The patch also fixes the following issue: Custom blocks on our websites were executed twice but rendered once. This caused an issue when using tempstore.private service in a block. After retrieving the values of tempstore.private we delete the values in tempstore.private. When executed twice no value is available.

This is my first issue-comment ever. I'm not sure if I can post a related problem in this comment. I did not yet find a related issue.

gisle’s picture

coretex,
best practice is to create a separate issue for a related problem.

You can link them by means of the "Related issues"field.

ghost of drupal past’s picture

Generic, handwavy shameless advertisement: https://www.drupal.org/project/twig_capture helps with one kind of double rendering issue. Might or might not help you.

maursilveira’s picture

Hello,

Patch #30 resolved the issues I was having with IDs changing for view blocks, custom plugin blocks, forms and form elements.

Thank you @GoZ!

maursilveira’s picture

Status: Needs review » Reviewed & tested by the community
alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs tests

Committed and pushed 30523436ce7 to 10.0.x and 4387ed5ba76 to 9.4.x and 26b81c40ab0 to 9.3.x. Thanks!

  • alexpott committed 3052343 on 10.0.x
    Issue #3254328 by GoZ, GOT intermedia, PapaGrande: Update to Drupal 9.3....

  • alexpott committed 4387ed5 on 9.4.x
    Issue #3254328 by GoZ, GOT intermedia, PapaGrande: Update to Drupal 9.3....

  • alexpott committed 26b81c4 on 9.3.x
    Issue #3254328 by GoZ, GOT intermedia, PapaGrande: Update to Drupal 9.3....
thomaswalther’s picture

  • -patch 26b81c40ab0 from #37 worked for me (also in a flexslider view)
  • -quickfix patch #19 worked for me (but not for flexslider view)

Thanks!

terminator727’s picture

Will there be a permanent solution in the future?
After each "composer update" do I have to use the patch again...

goz’s picture

Yes you still have to patch for the moment.

It's been commited and will be available with the next non-security release.

Next release should be in few days according https://www.drupal.org/about/core/policies/core-release-cycles/schedule :
First Wednesday (1200 UTC Tuesday - 1200 UTC Thursday) of every month

kevin.pfeifer’s picture

@terminator727 Instead of manually applying patches after each composer update you can define patches in your composer.json so they are applied automatically

See https://groups.drupal.org/node/518975

terminator727’s picture

@kevin.pfeifer
thanks for this information :)

Status: Fixed » Closed (fixed)

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

tgoeg’s picture

Still seeing this on a 10.1 site on a page where a subnavigation is put into one block as well as a Webform into another. The additional ID is only added when loading the second page of the form (which is not configured to use AJAX).

Changing CSS to target the class and not the ID (as advised above) solves it for me, but still this seems like a lurking bug.