CMS Development

Amit_95
Participant | Partenaire solutions Platinum
Participant | Partenaire solutions Platinum

Printing child links using the menu function

Résolue

I have a menu in the HubSpot backend configured like this:

 

Screenshot 2020-08-25 at 10.12.30.png

 

I'm trying to use the menu function to print out the markup of the above menu.

 

At the moment, I have:

 

{% set menu = menu(module.menu) %}
{% for item in menu.children %}
  <li class="{{ item.label|lower|replace(' ', '-') }}">
    <a href="{{ item.url }}">{{ item.label }}</a>
  </li>
{% endfor %}

 

But the above only prints the markup for top level links, not the child links underneath them. So it prints the following markup:

 

<li class="get-connected">
  <a href="#">Get connected</a>
</li>

<li class="register">
  <a href="#">Register</a>
</li>

<li class="tracks">
  <a href="#">Tracks</a>
</li>

 

How can I get it so that it prints the child markup too? So, what I am looking for is this (example):

 

<li class="get-connected">
  <a href="#">Get connected</a>
  <ul>
    <li>FF Studio</li>
    <li>FF Blog</li>
  </ul>
</li>

 

0 Votes
1 Solution acceptée
MPeric
Solution
Membre

Printing child links using the menu function

Résolue

Just to piggyback on this since this is not a working solution and I didn't find a lot of useful info online.
Regarding this:

 

 

{% set default_node = menu("default") %}
<ul>
  {% for child in default_node.children %}
    {% if child.level == 1 %}
    <li><a href="{{ child.url }}">{{ child.label }}</a></li>
    {% else %}
    <li>
      <ul>
        <li><a href="{{ child.url }}">{{ child.label }}</a></li>
      </ul>
    </li>
    {% endif %}
  {% endfor %}
</ul>

 

 

This will not generate the child elements. It will yield the same results as the code from the original question (the code is basically the same with one extra condition added which does not affect the output).
Here is the code from the original question:

 

 

{% set menu = menu(module.menu) %}
{% for item in menu.children %}
  <li class="{{ item.label|lower|replace(' ', '-') }}">
    <a href="{{ item.url }}">{{ item.label }}</a>
  </li>
{% endfor %}

 

 

However, after exploring the output of menu fuction, here is the working solution with macro included:

 

{% macro generateMenuMarkup(menuId) %}
  {% set menu = menu(menuId) %}
  {% for child in menu.children %}
    <h2>{{child.label}}</h2>
    <ul>
      {% for node in child.children %}
        <li>{{node.label}}</li>
      {% endfor %}
    </ul>
  {% endfor %}
{% endmacro %}

 

Calling this macro is simple as {{ generateMenuMarkup(module.menu) }}

Calling the macro with the following menu:

MPeric_0-1652275586929.png

Will yield following markup:

 

<h2>LINK-1</h2>
<ul>
  <li>LINK-1-1</li>
  <li>LINK-1-2</li>
  <li>LINK-1-3</li>
</ul>
<h2>LINK-2</h2>
<ul>
  <li>LINK-2-1</li>
  <li>LINK-2-2</li>
  <li>LINK-2-3</li>
</ul>

 

This way, you have complete control over markup regarding menus.
One additional benefit is that you can use hubl tokens directly in your menu and they will be properly rendered in your hubl markup which is not the case when you include menu directly with hubl snippet:

{% menu id="{{ module.user_logged_in_menu }}" %}
Example:
MPeric_1-1652276562649.png

When using macro and menu() function the content.absolute_url value (https://www.somelink.com) will be rendered.
When using hubl menu snippet, {{ content.absolute_url }} will be rendered as a simple string and value will not be inserted.

 

NOTE: This code will work for menus which are 1 level deep. For deeper menus more for loops will be needed.


Kind regards,
Milos

 

Voir la solution dans l'envoi d'origine

0 Votes
6 Réponses
MPeric
Solution
Membre

Printing child links using the menu function

Résolue

Just to piggyback on this since this is not a working solution and I didn't find a lot of useful info online.
Regarding this:

 

 

{% set default_node = menu("default") %}
<ul>
  {% for child in default_node.children %}
    {% if child.level == 1 %}
    <li><a href="{{ child.url }}">{{ child.label }}</a></li>
    {% else %}
    <li>
      <ul>
        <li><a href="{{ child.url }}">{{ child.label }}</a></li>
      </ul>
    </li>
    {% endif %}
  {% endfor %}
</ul>

 

 

This will not generate the child elements. It will yield the same results as the code from the original question (the code is basically the same with one extra condition added which does not affect the output).
Here is the code from the original question:

 

 

{% set menu = menu(module.menu) %}
{% for item in menu.children %}
  <li class="{{ item.label|lower|replace(' ', '-') }}">
    <a href="{{ item.url }}">{{ item.label }}</a>
  </li>
{% endfor %}

 

 

However, after exploring the output of menu fuction, here is the working solution with macro included:

 

{% macro generateMenuMarkup(menuId) %}
  {% set menu = menu(menuId) %}
  {% for child in menu.children %}
    <h2>{{child.label}}</h2>
    <ul>
      {% for node in child.children %}
        <li>{{node.label}}</li>
      {% endfor %}
    </ul>
  {% endfor %}
{% endmacro %}

 

Calling this macro is simple as {{ generateMenuMarkup(module.menu) }}

Calling the macro with the following menu:

MPeric_0-1652275586929.png

Will yield following markup:

 

<h2>LINK-1</h2>
<ul>
  <li>LINK-1-1</li>
  <li>LINK-1-2</li>
  <li>LINK-1-3</li>
</ul>
<h2>LINK-2</h2>
<ul>
  <li>LINK-2-1</li>
  <li>LINK-2-2</li>
  <li>LINK-2-3</li>
</ul>

 

This way, you have complete control over markup regarding menus.
One additional benefit is that you can use hubl tokens directly in your menu and they will be properly rendered in your hubl markup which is not the case when you include menu directly with hubl snippet:

{% menu id="{{ module.user_logged_in_menu }}" %}
Example:
MPeric_1-1652276562649.png

When using macro and menu() function the content.absolute_url value (https://www.somelink.com) will be rendered.
When using hubl menu snippet, {{ content.absolute_url }} will be rendered as a simple string and value will not be inserted.

 

NOTE: This code will work for menus which are 1 level deep. For deeper menus more for loops will be needed.


Kind regards,
Milos

 

0 Votes
Anton
Expert reconnu | Partenaire solutions Diamond
Expert reconnu | Partenaire solutions Diamond

Printing child links using the menu function

Résolue

Hi @Amit_95

you don't need a for loop to display the menu if you're using this hubl code.

Simply paste it in your module/template and leave the id blank. When building a page you can select the desired menu. HubSpot will automaticly translate the hubl into the right menu structure. 

 

Tipp: The ID is a bit hidden but can be found after selecting the menu once and previewing the page. When you inspect the sourcecode of the page/menu you should see this line(s):

Bildschirmfoto 2020-08-25 um 19.29.13.png The "data-menu-id" is your menu ID. So after you found it you can go back to your module/template and paste it in. By doing this you won't need to select the menu everytime you're building a page.

 

 

best, 

Anton

Anton Bujanowski Signature
0 Votes
Amit_95
Participant | Partenaire solutions Platinum
Participant | Partenaire solutions Platinum

Printing child links using the menu function

Résolue

Hi @Anton,

 

The reason I'm running the for loop is so that I can have control over the menu's markup (don't want those spans).

 

The docs for the menu function I'm using is here. However, in the docs, it doens't say how I can print child items?

0 Votes
Anton
Expert reconnu | Partenaire solutions Diamond
Expert reconnu | Partenaire solutions Diamond

Printing child links using the menu function

Résolue
If you want to get rid of the spans, simply add "no_wrapper=True" to your menu hubl code.

It should look like this:

{% menu "my_menu" id=456, flyouts='true', max_levels='2', flow='horizontal', label='Advanced Menu', no_wrapper=True %}

Best,
Anton
Anton Bujanowski Signature
0 Votes
Amit_95
Participant | Partenaire solutions Platinum
Participant | Partenaire solutions Platinum

Printing child links using the menu function

Résolue

Hi @Anton 

 

It's not just the span I want to remove, it's the unncessary classes and data attributes that come alongside this appoach too. Whilst your approach does the job, I'm looking to be in complete control of the markup that is generated within my list items.

 

Are you suggesting there is no way for me achieve this with the partial approach HubSpot have defined here?

0 Votes
Anton
Expert reconnu | Partenaire solutions Diamond
Expert reconnu | Partenaire solutions Diamond

Printing child links using the menu function

Résolue

Hi @Amit_95

if you want to work with this code it's fine. I've modified you the code:

{% set default_node = menu("default") %}

<ul>
  {% for child in default_node.children %}
{% if child.level == 1 %}
  <li><a href="{{ child.url }}">{{ child.label }}</a></li>
{% else %}
  <li>
    <ul>
    <li><a href="{{ child.url }}">{{ child.label }}</a></li>
  </ul>
  </li>
{% endif %}
{% endfor %}
</ul>

 

 

 

 

But if you want to completly modify it and have complete control over your menu try this:

Write your own menu Module

 

 

It's easier than it sounds.

Here's my code:

 

{# Config #}
{% for item in module.single_nav_entry %}{% set href = item.menu_url.url.href %}
{% if item.menu_url.url.type is equalto "EMAIL_ADDRESS" %}
{% set href = "mailto:" + href %}
{% endif %}
{% endfor %}

{# Code #}
<ul>
  {% for item in single_nav_entry %}
  {% if item.child %}
  <li>
    <ul>
    <li class="{{item.custom_class}}"><a href="{{ href }}"{% if item.menu_url.open_in_new_tab %}target="_blank"{% endif %}{% if item.menu_url.no_follow %}rel="nofollow"{% endif %}>{{ item.menu_name }}</a></li>
    </ul>
  </li>
  {% else %}
  <li class="{{item.custom_class}}"><a href="{{ href }}"{% if item.menu_url.open_in_new_tab %}target="_blank"{% endif %}{% if item.menu_url.no_follow %}rel="nofollow"{% endif %}>{{ item.menu_name }}</a></li>
  {% endif %}
  {% endfor %}
</ul>

 

 

and here some screens of the module functions/widgets:

module widgetsmodule widgetsgroup settingsgroup settings

 

If you want to use it as a global element don't forget to select "global module" when creating the module. If you want to use the module in a global group you don't need to do this. 

 

 

best,

Anton

Anton Bujanowski Signature
0 Votes