1

I am trying to insert the languageswitcher block and login block into the menu. So basically I am after inserting custom html into menu or change the html of a menu link.

Looks like the best place to do this is hook_preprocess_menu(). A dirty workaround is adding it under a desired menu item by finding that item with a condition check.

But there should be a more "Drupal way" of doing it. In Drupal 7, AFAIR, I could set the whole html of a menu item. But as you can see in the following kint() output, I couldn't find room to do that.

enter image description here

Here is my workaround:

function mytheme_preprocess_menu(&$variables) {
  if (isset($variables['menu_name']) && $variables['menu_name'] == 'main') {
    foreach ($variables['items'] as &$item) {
      $attributes = $item['url']->getOption('attributes');
      if (isset($attributes['class']) && in_array('locale', $attributes['class'])) {
        if ($block = \Drupal\block\Entity\Block::load('languageswitcher')) {
          $copy = $item;
          $item['is_expanded'] = true;
          $copy['locale'] = \Drupal::entityTypeManager()
            ->getViewBuilder('block')
            ->view($block);
          $item['below'][] = $copy;
        }
      }
    }
  }
}

The condition I check here is a class I added with the menu_link_attributes module.

Then I print it in menu--main.html.twig. I am using a Bootsrap submenu and putting here the whole code for reference:

{% import _self as menus %}

{#
  We call a macro which calls itself to render the full tree.
  @see http://twig.sensiolabs.org/doc/tags/macro.html
#}
{{ menus.menu_links(items, attributes, 0) }}

{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('menu', 'nav', 'navbar-nav') }}>
    {% else %}
      <ul{{ attributes.addClass('dropdown-menu') }}>
    {% endif %}
    {% for item in items %}
      {%
        set item_classes = [
          item.is_expanded? 'expanded',
          item.is_expanded and menu_level == 0 ? 'dropdown',
          item.in_active_trail ? 'active',
        ]
      %}
      {% if menu_level == 0 and item.is_expanded %}
        <li{{ item.attributes.addClass(item_classes) }}>
        <a href="{{ item.url }}" class="dropdown-toggle" data-target="#" data-toggle="dropdown">{{ item.title }} <span class="caret"></span></a>
      {% elseif item.locale %}
        {{ item.locale }}
      {% else %}
        <li{{ item.attributes.addClass(item_classes) }}>
        {{ link(item.title, item.url) }}
      {% endif %}
      {% if item.below %}
        {{ menus.menu_links(item.below, attributes.removeClass('nav', 'navbar-nav'), menu_level + 1) }}
      {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %} 

So the actual question is, what is the Drupal way of doing this?

4
  • How does your menu item looks like, This is an <p>Example</p>. Something like this? What is your input and your expectation? Commented Mar 24, 2017 at 9:57
  • @FazeelaAbuZohra: By design the additonal html parts look like they are part of the menu. If you click on menu item Locale, you get to switch to other languages.
    – duru
    Commented Mar 24, 2017 at 10:02
  • Can you check whether this is what you're looking for drupalyourselves.blogspot.in/2017/03/… Commented Mar 24, 2017 at 10:06
  • @FazeelaAbuZohra: Link is a workaround for this question: drupal.stackexchange.com/questions/215826/…
    – duru
    Commented Mar 24, 2017 at 10:17

0

Your Answer

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

Browse other questions tagged or ask your own question.