0

Im trying to use bootstrap for an accordion menu. My issue is that I need unique ID's for each accordion item. I found some similar topics here: Add Unique ID to Menu Item and here: How to add a custom variable that can be accessed on bootstrap's menu--account.html.twig?

Id like to know how I can get a unique ID for each item. Preferably an ID I can store within a variable which I can then pass to the data target attribute. As you can see in my code below, I'm trying to achieve something like that. The issue is that I cannot use the variable in a twig template that I declared within the preprocess function. Help me understand what I'm doing wrong.

Here is my code in my .theme file:

function my_theme_preprocess_menu__main(array &$variables) {
    $id = 0;
    foreach ($variables['items'] as $key => $item) {
      $variables['items'][$key]['accordionNav']=[];
      $key_hash = hash('crc32b', $key);
      $variables['items'][$key]['accordionNav'] = $key_hash ;
}
}

Here is my twig file menu--main.html.twig:

{% 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('nav navbar-nav').setAttribute('id', 'accordion') }}>
    {% else %}
      <ul class="sub-menu card-body">

    {% endif %}

    {% for item in items %}

      {%
        set classes = [
          menu_level ? 'sub-item' : 'nav-item',
          item.in_active_trail ? 'active',
          item.below ? 'card',
        ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
        {%
          set link_classes = [
            not menu_level ? 'nav-link',
            item.in_active_trail ? 'active',
            item.url.getOption('attributes').class ? item.url.getOption('attributes').class | join(' '),
            'nav-link-' ~ item.url.toString() | clean_class,
          ]
        %}
        {% if item.below %}
        {% if item.in_active_trail %}
        <div class="card-header" id="heading{{ip}}">
        <button class="btn btn-link" data-toggle="collapse" data-target="{{accordionNav}}" aria-expanded="true" aria-controls="collapse{{ip}}">

          {{ item.title }}
         </button>
         </div>

         <div id="collapse{{ip}}" class="collapse show" aria-labelledby="heading{{ip}}" data-parent="#accordion">
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
          {% else %}
          <div class="card-header" id="heading{{ip}}">
        <button class="btn btn-link" data-toggle="collapse" data-target="{{accordionNav}}" aria-expanded="false" aria-controls="collapse{{ip}}">

          {{ item.title }}
         </button>
         </div>

         <div id="collapse{{ip}}" class="collapse" aria-labelledby="heading{{ip}}" data-parent="#accordion">
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
         {% endif %}

        </div>
        {% else %}
          {{ link(item.title, item.url, {'class': link_classes}) }}

        {% endif %}

      </li>

    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}
4
  • There is no question here
    – Hudri
    Commented Dec 16, 2020 at 20:15
  • Id like to know how I can get a unique ID for each item. Preferably an ID I can store within a variable which I can then pass to the data target attribute. As you can see in my code below, I'm trying to achieve something like that. The issue is that I cannot use the variable in a twig template that I declared within the preprocess function.
    – mfvill
    Commented Dec 16, 2020 at 22:19
  • What's the name of your twig file?
    – No Sssweat
    Commented Dec 16, 2020 at 22:46
  • name of my twig file is: menu--main.html.twig
    – mfvill
    Commented Dec 17, 2020 at 0:32

1 Answer 1

0

You could use directly the derivative id (which will be unique) of the menu item in twig, with:

item.original_link.getDerivativeId()

otherwise you need to add a custom unique id in preprocess function to each item, like:

function yourtheme_menu_link_alter(&$item) {
  if($item['menu_name'] == 'custom-menu')
  {
    $item['uuid'] = \Drupal\Component\Utility\Html::getUniqueId($item['menu_name']);
  }
}

which you then access in twig with:

item.uuid
3
  • Could you expand a bit more on this answer please?
    – mfvill
    Commented Dec 16, 2020 at 22:28
  • There you go ;)
    – rémy
    Commented Dec 17, 2020 at 22:44
  • thanks for the expalnation. Im having trouble setting the variable value. Here is my code to set the variable: {% set ids = ['nav-link-' ~ item.original_link.getDerivativeId() | clean_class] %} not sure if im doing this right.
    – mfvill
    Commented Dec 22, 2020 at 20:10

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.