Hey guys, trying to loop through a Menu item to output only only the sub-level items of the parent menu item. Wondering if anyone has any tips or tricks for this.
For example, my “Primary Menu” has:
About
Services
Portfolio
Inside the parent item “About” I have:
About (id: 687)
Brief History (id: 5)
Staff (id: 193)
Board (id: 482)
I am creating an aside menu on a page, and want to output the About Menu item and its child items only. Trying to avoid having to create a new menu item just for the aside menus.
I can see I can target the ID of About, and I can see that each of the child items have an ID, so I only want.
Wondering if anyone has any cool liquid logic for this? I’ll try it myself and if I come up with something I’ll post it here, but until then, if anyone has any suggestions, please let me know.
Hey @A3CS. In order to ‘detect’ which sub menu items are needed for the page I’d say you’d have to ensure that the parent menu item (About) has a URL set for that page (often dropdown menus don’t set any URL for the parent item). So assuming that’s ok, you’d then send your menu to a collection, so it’s accessible elsewhere on the page template. Then set up a loop through that collection where you want the sub menu to appear in your template, but have a condition to look for a match between current page URL and menu item URL. If a match found, then you can further loop through its child items and output only those.
Without the parent menu item having a URL set I’m not sure how you’d detect the relevant items - unless you used some other identifier in an unused menu item field.
Nice one @peter.medbury. This assumes though that we know the ID and are probably only creating one submenu. But if you wanted to dynamically render a submenu on any page that had submenu items in the main nav it’s this line that somehow needs to be dynamic: {% if i.ID == 687 %}
I first thought that matching the page URL to the menu item URL would be the way to do this. Ie. something like: {% if i.url == request.request_url.path %}
But this won’t work as you won’t be on that parent level page…
I think to do it dynamically you’d really need some sort of matching directory structure to know what a subpages parent was.
Any thoughts on doing that? @A3CS are you trying to do this dynamically for multiple pages or is it just a one-off where a hard-coded ID is ok?
You might map the menu system to a nested custom module structure but I’d be concerned at the overhead.
I’d be looking to use the Custom Attribute for the Menu Item in some way.
{{this.itemcustomattribute}}
The code to render the menu would have to be on every page where a submenu might be rendered. It would have to compare the CustomAttribute to something the code can resolve about the page being loaded.
The simplest flag might be set the CustomAttribute in the Menu Item for every page that a submenu will be loaded on. Different attribute values could trigger different submenus That way you could display any submenu on any page or no submenu if the attribute is NULL.
It’s easy enough to iterate through a multi-level level menu system.
I am working on a web site at the moment that has multiple submenus. It all depends on how many levels you want.
This code block produces a multilevel menu. It is the menu.layout for the menu.:
<div class="navbar-collapse nav-main-collapse collapse">
<nav class="nav-main">
<ul id="topMain" class="nav nav-pills nav-main">
{% if this.items -%}
{% for i in this.items -%}
{% assign isSelected = "" %}
{% if request.request_url.path == i.itemUrl %}
{% assign isSelected = "active" %}
{% endif -%}
{% if i.items != null -%}
<li class="dropdown {{isSelected}}">
<a class="dropdown-toggle" href="{{i.itemUrl}}">{{i.itemName}}</a>
<ul class="dropdown-menu">
{% for j in i.items -%}
{% if j.items != null -%}
<li>
<a class="dropdown-toggle" href="{{j.itemUrl}}">{{j.itemName}}</a>
<ul class="dropdown-menu">
{% for k in j.items -%}
{% if k.items != null -%}
<li>
<a class="dropdown-toggle" href="{{k.itemUrl}}">{{k.itemName}}</a>
<ul class="dropdown-menu">
{% for l in k.items -%}
{% if l.items != null -%}
<li>
<a class="dropdown-toggle" href="{{l.itemUrl}}">{{l.itemName}}</a>
<ul class="dropdown-menu">
{% for m in l.items -%}
{% if m.items != null -%}
<li>
<a class="dropdown-toggle" href="{{m.itemUrl}}">{{m.itemName}}</a>
<ul class="dropdown-menu">
{% for n in m.items -%}
{% if n.items != null -%}
<li><a class="dropdown-toggle" href="{{n.itemUrl}}">{{n.itemName}}</a>
{% else -%}
<li><a href="{{n.itemUrl}}">{{n.itemName}}</a>
{% endif -%}
{% endfor -%}
</ul>
{% else -%}
<li><a href="{{m.itemUrl}}">{{m.itemName}}</a>
{% endif -%}
</li>
{% endfor -%}
</ul>
{% else -%}
<li><a href="{{l.itemUrl}}">{{l.itemName}}</a>
{% endif -%}
</li>
{% endfor -%}
</ul>
{% else -%}
<li><a href="{{k.itemUrl}}">{{k.itemName}}</a>
{% endif -%}
</li>
{% endfor -%}
</ul>
{% else -%}
<li><a href="{{j.itemUrl}}">{{j.itemName}}</a>
{% endif -%}
</li>
{% endfor -%}
</ul>
{% else -%}
<li class="{{isSelected}}"><a href="{{i.itemUrl}}">{{i.itemName}}</a>
{% endif -%}
</li>
{% endfor -%}
{% endif -%}
</ul>
</nav>
</div>
I finally needed this functionality - present items from a menu in a multi-column, variable length list that auto adjusts as items are added or deleted.
Maybe I could have used the new Menu Layout functionality but this does it.
I wanted 3 columns & from inspection I knew the Menu Item I wanted was the 8th.
I could have found it by iterating & checking against the itemName. Knowing exactly which Menu Item avoided the extra processing.
Parent Menu Item Found using:
<pre>{{menuData.items}}</pre>
Confirmed the Submenu Items via:
<pre>{{menuData.items[8]}}</pre>
Implemented in the following manner using Liquid to determine the number of rows in each column: