3

I've worked with twig and have overriden most of elements in my application. However, I it is not clear to me how I can overwrite the menu template for specific node-types. The suggestions I get from the theming debug are too general and not node specific. Any ideas on how to register a twig template for menu for specific node types?

2 Answers 2

4

Menus do things a little differently then, so you have an option or two...

/**
 * Implementation of hook_theme_suggestions_alter().
 */
function mymodule_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($hook == 'menu' && ($node = \Drupal::routeMatch()->getParameter('node'))) {
    $content_type = $node->bundle();
    $suggestions[] = 'menu__node_type__%';
    $suggestions[] = 'menu__node_type__'.$content_type;
  }
}

This will give you give you the following suggestion in this order:

  • menu--MENU-NAME.html.twig
  • menu--node-type--page.html.twig
  • menu--node-type--%.html.twig
  • menu.html.twig

With this the menu--MENU-NAME template still takes preference over the node type, so we need a trick to add suggestions after.

/**
 * Implementation of hook_theme_suggestions_HOOK_alter().
 */
function mymodule_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  $key = array_search('menu__'.$variables['menu_name'], $suggestions);
  if ($key !== FALSE && ($node = \Drupal::routeMatch()->getParameter('node'))) {
    $content_type = $node->bundle();
    array_splice($suggestions, ++$key, 0, array('menu__node_type__%', 'menu__node_type__'.$content_type));
  }
}
  • menu--node-type--page.html.twig
  • menu--node-type--%.html.twig
  • menu--main.html.twig
  • menu.html.twig

Targeting your placement within the array of suggestions can be helpful, but it can be over kill, so you may just want to keep it simple and place your new suggestion at the end of the list and have the highest override

/**
 * Implementation of hook_theme_suggestions_HOOK_alter().
 */
function mymodule_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    $content_type = $node->bundle();
    $suggestions[] = 'menu__node_type__%';
    $suggestions[] = 'menu__node_type__'.$content_type;
  }
}

You can even throw $variables['menu_name'] into the mix with:

$suggestions[] = 'menu__'.$variables['menu_name'].'__node_type__%';
$suggestions[] = 'menu__'.$variables['menu_name'].'__node_type__'.$content_type;
0
0

I did not try it myself, but the tip described in https://www.drupal.org/node/2521876 explains how to add a custom suggestion based on the node type, using the hook_theme_suggestions_HOOK_alter hook:

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

  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    $content_type = $node->bundle();
    $suggestions[] = 'page__'.$content_type;
  }
}

The solution above seems to work for adding page suggestions. You might want to adapt it to add menu suggestions instead, with THEME_NAME_theme_suggestions_menu_alter as the function name.

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.