2

I'm placing the same menu block in two different regions whereas different html markup for the list is needed. So analog to my previous question "How to make a theme hook suggestion for blocks according to region?" I need to know, how to get the current region inside the function MYMODULE_theme_suggestions_menu_alter, to add my own suggestion.

bumped to the homepage by Community 2 days ago

This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.

0

This is a bit of a hacky solution, but it worked for me. Only difference is that I needed to do it to search forms, but it should be equally applicable to your situation.

use Drupal\block\Entity\Block;

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MODULE_theme_suggestions_form_alter(array &$suggestions, array $variables) {

  if($variables['element']['#form_id'] === 'search_block_form') {

    if(isset($variables['element']['#id']) && !empty($variables['element']['#id'])) {

      if($variables['element']['#id'] === 'search-block-form') {
        $block = Block::load('searchform');
      }
      else if($variables['element']['#id'] === 'search-block-form--2') {
        $block = Block::load('searchform_2');
      }

      if(isset($block) && !empty($block)) {
        $suggestions[] = 'form__' . $block->getRegion();
        $suggestions[] = 'form__' . $block->getRegion() . '_searchform';
      }
    }
  }

  return $suggestions;
}

Explanation of code: Remember to change the function name to use the correct hook!

if($variables['element']['#form_id'] === 'search_block_form') {
  ...
}

I do this, so that my suggestions only affect the search block form, you should change this to a check for the right menu, so your suggestions only affect the menu you need it for.

if(isset($variables['element']['#id']) && !empty($variables['element']['#id'])) {
  ...
}

This is just to prevent errors in case I hit a form that doesn't have an id.

if($variables['element']['#id'] === 'search-block-form') {
  $block = Block::load('searchform');
}
else if($variables['element']['#id'] === 'search-block-form--2') {
  $block = Block::load('searchform_2');
}

This is what I consider the "hacky" bit, basically I check for the id's of the forms (in this case search-block-form and search-block-form--2), and then proceed to load the appropriate block (the block id's used for loading the blocks, are just the machine names give to the blocks).

if(isset($block) && !empty($block)) {
  $suggestions[] = 'form__' . $block->getRegion();
  $suggestions[] = 'form__' . $block->getRegion() . '_searchform';
}

Here I just add the suggestions, I add 2 suggestions, but you can probably justify only adding one.


I really hope this helps, feel free to suggest changes to my code.

0

Joery Lemmens posted an answer to a similar question on Drupal's forums:

use Drupal\block\Entity\Block;

/**
 * Implements hook_preprocess_HOOK().
 *
 * Pass block region value to content so this can be used in
 * MYTHEME_theme_suggestions_menu_alter.
 */
function MYTHEME_preprocess_block(&$variables) {
  if (isset($variables['elements']['#id'])) {
    $region = Block::load($variables['elements']['#id'])->getRegion();
    $variables['content']['#attributes']['region'] = $region;
  }
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 *
 * Provide region based menu suggestions.
 */
function MYTHEME_theme_suggestions_menu_alter(&$suggestions, array $variables) {
  if (isset($variables['attributes']['region'])) {
    $suggestions[] = 'menu__' . $variables['menu_name'] . '__' . $variables['attributes']['region'];
  }
}

All credit to Joery for this elegant solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.