2

I have a menu that want to behave differently based on the region its displayed in.

By default there is no file suggestion that differentiates which twig file to be used for a menu based on the region. Even if there was I think for the purpose of adding/removing a class it is more convinient to modify a variable in a preprocess function than keeping to versions of a twig template.

here is what I have

function THEMENAME_preprocess_menu(&$vars) {
    $test = "";
    if ($vars['menu_name'] == 'main') {
        if (!isset($vars['attributes']['class'])) {
            $vars['attributes']['class'] = [];
        }
        //test region or block name before merging
        $vars['attributes']['class'] = array_merge($vars['attributes']['class'], ['main-menu-regionA']);  
    }
}

I need a way to test the region or the block name to add a specific class to the parent UL element

my 2nd choice would be to explore the hook_theme_suggestions_alter

1 Answer 1

3

hook_preprocess_menu is missing a lot of variables that other preprocessors have so I finally solved my problem using hook_preprocess_block (which I think would not have been possible in earlier versions of drupal)

New solution since people have been reporting that $vars['configuration']['region'] is empty

function THEMENAME_preprocess_block(&$vars){
    if($vars['base_plugin_id'] == "system_menu_block"){
        if($vars['derivative_plugin_id'] == "main"){           
            $block = \Drupal\block\Entity\Block::load($vars["elements"]["#id"]);
            if( $block->getRegion() == "navbar")
                $vars['content']['#attributes']['class'][] = 'in-navbar';
                $vars['content']['#attributes']['class'][] = 'nav';
            }
            elseif($vars['configuration']['region'] == "footer"){
                $vars['content']['#attributes']['class'][] = 'in-footer';
            }
        }
    }
}

NOTE if using in a recursive function/twig MACRO (which probably you are) you should removeClass all the classes you don't want in inner UL tags in a way similar to this

{{ menus.menu_links(item.below, attributes.removeClass('nav','in-navbar'), menu_level + 1) }}

old solution

function THEMENAME_preprocess_block(&$vars){
    if($vars['base_plugin_id'] == "system_menu_block"){
        if($vars['derivative_plugin_id'] == "main"){           
            if($vars['configuration']['region'] == "navbar"){
                $vars['content']['#attributes']['class'][] = 'in-navbar';
                $vars['content']['#attributes']['class'][] = 'nav';
            }
            elseif($vars['configuration']['region'] == "footer"){
                $vars['content']['#attributes']['class'][] = 'in-footer';
            }
        }
    }
}
2
  • This didnt actually work for me because ['region'] was missing from the $vars['configuration'] but drupal.stackexchange.com/a/218926/3167 worked. Commented Nov 17, 2017 at 15:38
  • just checked and I am not doing anything special to get region in configuration ... strange
    – GiorgosK
    Commented Nov 17, 2017 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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