0

I am using Drupal with the Commerce Module to build a webshop. I am using the Commerce Cart Block to display a cart icon with the amount of items in the cart, in the navigation bar.

Now I would also like to display the Cart Block on the Cart page, but with a different template than being used in the navigation bar.

I am using the debug mode, which let me see what I could call the file names to use them like I would like to. But above both Cart Blocks it says the same file name, so I can't output two different templates. I tried putting primary_menu-- before the navigation cart block and content-- (the region the cart block is going to be in), but they don't work.

<!-- THEME DEBUG -->
<!-- THEME HOOK: 'commerce_cart_block' -->
<!-- BEGIN OUTPUT from 'themes/custom/verdamigo/templates/commerce-cart-block.html.twig' -->

This is shown above both cart blocks (which are on the same page). So how can I use two different templates for both blocks.

primary_menu--commerce-cart-block.html.twig

is not working.

I would like to be able to edit both the block in the primary_menu and the block in the content-region. But both carts get output with the same template.

Mxkert
  • 346
  • 2
  • 5
  • 17

1 Answers1

1

In an effort to decouple Blocks from Displays, Drupal 8 renders a block independently of which display it's in and what region/weight it has in that display (see Twig Template naming conventions) :

Region-specific block templates are not available in Drupal 8.

This removes the ability to override block.tpl.php by region, and for hook_preprocess_block() to adjust variables based on it. Instead, core developers recommend to manage block template overrides with CSS or using additional blocks.

But you can still work around this by implementing hook_theme_suggestions_HOOK_alter() :

function SOME_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  if (!empty($variables['elements']['#id'])) {
    $block_id = $variables['elements']['#id'];
    $block = Drupal\block\Entity\Block::load(block_id);
    $region = $block->getRegion();
    // Allow per-region block templating.
    $suggestions[] = 'block__' . $region . '__' . $block_id;
  }

  return $suggestions;
}

Note : the template name should begin with "block" since you override a block template, so in your case the override file should be named block--primary_menu--commerce-cart-block.html.twig.

EricLavault
  • 12,130
  • 3
  • 23
  • 45
  • Thank you for the detailed answer. Do I put this code on the bottom of `../modules/contrib/commerce/commerce.module`? What is the next step after that? I did read the documentation, but I'm not quite sure if I'm doing this right, never worked with hooks before. – Mxkert Apr 23 '19 at 10:47
  • And do I use `SOME_theme_suggestions_block_alter` or `commerce_theme_suggestions_block_alter`? – Mxkert Apr 23 '19 at 11:00
  • 1
    No, you should rather create your own module/theme instead of overriding contributed ones (to prevent loosing changes or having to keep track and apply patches at each upgrade, and things/features/code are easier to decouple when kept separated). Then for example, in a module named "mymodule", you would implement the hook with the function `mymodule_theme_suggestions_block_alter`. I strongly recommend you dig into the [hook system](https://www.drupal.org/docs/8/creating-custom-modules) and how it works, it is essential to be able to interact with core and other modules. – EricLavault Apr 23 '19 at 11:35
  • Please consider upvoting every answers you find useful ;) Thanks ! – EricLavault Apr 23 '19 at 11:35
  • I did create a custom module, named Rename Block, with a `rename_block.info.yml` and a `rename_block.module` file. The module can be found and is enabled. I put your piece of code in the `rename_block.module` file. Now I get a big error on my site, which includes the following line: `Error: Call to a member function getRegion() on null in rename_block_theme_suggestions_block_alter() (line 7 of modules/custom/rename_block/rename_block.module).`. What am I doing wrong? – Mxkert Apr 24 '19 at 07:49
  • 1
    `Drupal\block\Entity\Block::load(block_id);` returns `null` instead of a drupal block object, probably because you pass in a wrong/inexistant `block_id`. From that, the error is "normal", there is no `getRegion()` method to call on a null object. Double check your target block_id so that the corresponding block can be loaded properly. – EricLavault Apr 24 '19 at 07:58