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.
-
If your menu is a block you can add suggestion add block level, as described here drupal.stackexchange.com/questions/192616/…, if you want to be specific just check if your block is a menu before add suggestion,– VagnerMar 7, 2016 at 17:24
-
Have a look here, I was querying regions to implement some better theming. Not sure if this will help: drupal.stackexchange.com/q/193701/697– Danny EnglanderMar 8, 2016 at 3:28
-
I need to alter the ul and nested li of the menu, so hooking at block or region level won't help, I guess.– Philipp MichaelMar 8, 2016 at 7:43
2 Answers
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.
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.