2

I'm attempting to give menus more variables to work with besides the default menu_name,items, and attributes. This is because making a variable in the preprocess menu hook does not allow it to be accessible in the menu.html.twig template.

My ultimate goal is to be able to add menu items that contain the user id in the path.

I believe I need to add the var to menu by using hook_theme_registry_alter and follow the format of https://api.drupal.org/api/drupal/core%21includes%21theme.inc/function/drupal_common_theme/8.2.x

So I attempted to add a variable to menu in my .theme file like so

function mytheme_theme_registry_alter(&$theme_registry){
    $theme_registry['menu']['variables']['test_var'] = 'testing theme registry alter';
}

But when I do so nothing appears when I alter menu.html.twig like so

<nav {{ attributes.addClass(navClasses) }} aria-label="MyWPT Menu Mobile" role="navigation" style="display:none;">
    {{ menus.menu_links(items, attributes, 0) }}
{#     {% macro menu_links(items, attributes, menu_level) %} #}
    {% macro menu_links(items, attributes, menu_level) %}
    {% import _self as menus %}
    {% if items %}
    {% if menu_level == 0 %}
    <ul class="vertical menu" data-drilldown>
        {% else %}
        <ul class="vertical menu">
            {% endif %}
            {% for item in items %}
                {% if item.below %}
                    <li class="is-dropdown-submenu-parents">
                {% else %}
                    <li{{ item.attributes }}>
                {% endif %}
                {{ link(item.title, item.url) }}
                {% if item.below %}
                    {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
                {% endif %}
                </li>
            {% endfor %}

            <li><a href="/">{{ test_var }}</a></li>
        </ul>
        {% endif %}
        {% endmacro %}

How would I add more menu variables for use in menu.html.twig ?

UPDATE: I also tried {{menus.test_var}} but that just broke the page

UPDATE 2: Using {{ kint() }} the test_var did not appear anywhere

6
  • Did you clear the cache?
    – Kevin
    Oct 2, 2017 at 18:04
  • Yes the cache has been cleared
    – Amy
    Oct 2, 2017 at 18:06
  • I think it expects an array, not a string: api.drupal.org/api/drupal/…
    – Kevin
    Oct 2, 2017 at 18:27
  • But I'm adding a custom var. Why would it matter what variable type it is? In the theme registry not all variables are arrays 'menu' => array( 'variables' => array('menu_name' => NULL, 'items' => array(), 'attributes' => array()), The menu name is just a string ),
    – Amy
    Oct 2, 2017 at 18:32
  • You did not pass a variable in an array, you only passed a string.
    – Kevin
    Oct 2, 2017 at 18:35

3 Answers 3

3

Here is an example from a real project I had done:

mytheme.theme:

/**
 * Implements hook_theme_registry_alter().
 * @param $theme_registry
 */
function mytheme_theme_registry_alter(&$theme_registry) {
  $theme_registry['menu']['variables']['top_parent'] = [];
}

/**
 * Implements hook_preprocess_block__menu_block().
 * @param $variables
 */
function mytheme_preprocess_block__menu_block(&$variables) {
  // set the top parent on the left nav
  if ($variables['elements']['#id'] == 'left_navigation' && !empty($variables['elements']['content']['#items'])) {
    // code removed

    $variables['content']['#top_parent'] = [
      'title' => $menu_content->getTitle(),
      'url' => $menu_content->getUrlObject(),
      'is_current' => ($current_path == $item_path)
    ];
  }

  // code removed
  }
}

In Twig:

  {% if menu_level == 0 %}
    <li class="left-nav__item active-trail is-active {% if top_parent.is_current %}is-current{% endif %}">
      {{ link(top_parent.title, top_parent.url) }}
    </li>
  {% endif %}

You are likely missing the part where you add test_var key to the content array:

$variables['content']['#test_var'] = "whatever";

With exception to flagging is-current, it looks like you're trying to do the same thing I did. You should strive to use the link function in Twig instead of a hard coded anchor unless there is no way around it.

1
  • 1
    Still doesn't work for me. Also I'm not using a block. I'm programmatically rendering the menu by rendering it in preprocess_page and storing it in a twig variable. And I'm assigning these variables inside preprocess_menu not preprocess_menu_block I've tried different versions like $vars['content']['#test_var'] $vars['test_var'] and $vars['#test_var'] all with no luck
    – Amy
    Oct 2, 2017 at 19:01
0

be careful to the name of your menu for example if you want to assign a new variables to main menu you must do something like this

function mytheme_theme_registry_alter(&$theme_registry) {
  $theme_registry['menu__main']['variables']['top_parent'] = [];
}
0

Sometimes theme hooks are specific so you might have node and node__mytype

Therefore, the theme registry array key to change is $theme_registry['node__mytype'] in addition to the normal one.

Here is a function to effect all variations.

/**
 * Implements hook_theme_registry_alter().
 */
function mythemename_theme_registry_alter(&$theme_registry) {
  $target_theme_hook = 'node';
  $target_theme_hooks = [];
  foreach (array_keys($theme_registry) as $theme_hook) {
    // Is target theme hook.
    if ($target_theme_hook === $theme_hook) {
      $target_theme_hooks[] = $theme_hook;
      continue;
    }
    // Is more specific version of the target theme hook.
    if (strpos($theme_hook, "{$target_theme_hook}__") === 0) {
      $target_theme_hooks[] = $theme_hook;
      continue;
    }
  }
  // Add $new_var as a variable to the 'node' theme hook(s) we 
  // collected eailer. Set its default value to be an
  // empty string.
  foreach ($target_theme_hooks as $target_theme_hook) {
    $theme_registry[$target_theme_hook]['variables']['new_var'] = '';
  }
}

Your Answer

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

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