Only display child menu elements associated with a specific section?

Context: I have a mainmenu that is defined in each sections Front Matter (e.g. not in the config.yaml) and displayed in the site header. Some of these sections have a submenu unique to that section.

The content folder is structured like this:

Content folder
content/pages/_index.md
content/pages/first-section
  - _index.md
  - coverimage.jpg
content/pages/secound-section
  - _index.md
  - coverimage.jpg
... etc.

The Front Matter in the _index.md files are structured like this:

Front Matter

Fist level menu elements

title: This is my stamp collection
linktitle: Stamps
menu:
  mainmenu:

Secound level menu elements

title: Stamps from Norway
linktitle: Norway
menu:
  mainmenu:
    sidebar_stamps:

Question: How do I display the relevant submenu for each section – without displaying all children on all sections? I want to keep duplicate code to a minimum (stay DRY).

Current solution: Make a separate partial file for every submenu/sidebar. In the baseof.html i then do;

{{ block "sidebar" . }}
{{ partial menus/sidebar_stamps "sidebar" }}
{{ end }}

…and {{ define "sidebar" }} in layout files under /layouts/pages/stamps.html/ and adding layout: stamps to the Front Matter. It kinda works but the logic is repeated for every submenu partial file. They look like this:

Partial file (repeated for each submenu I need)
<ul class="site-sidebar-menu">
    {{ $currentPage := . }
    {{ range .Site.Menus.sidebar_stamps }} <!-- "stamps" is different in each partial -->
        <div>
        <li class="button{{ if $currentPage.IsMenuCurrent "sidebar_stamps" . }} button-active{{- end -}}">
            <a href="{{ .URL }}">
                {{ .Pre }}
                {{ .Name }}
            </a>
        </li>
        </div>
    {{ end -}}
</ul>

I would like to use a variable that outputs the submenu name related to the specific section, like: .Site.Menus. $variable, so I do not have to make multiple partials for each submenu.

I have also experimented with the parent parameter in the menus in Front Matter in combination with {{ range .Child }} without any luck.

After having combed through the documentation, Google and this forum for hours, I still haven’t found a working solution. :pensive: This might be a problem related to my lack of experience with Go, but I hope someone can point me in the right direction!

Also, I want to give a big thanks to @bep and all contributors for the time you have spent making Hugo, I have really enjoyed working with it!

2 Likes

Ok, so after many hours of stumbling around in the dark, I found a solution to my problem. It turns out my lack of familiarity with the Go language was my biggest problem.

Quick summary: I made sure my sections folder name was the same as their menu names. This way I could use the {{ .Section }} variable to dynamically fetch the right menu for each section. Here is how I made sure a submenu was displayed only under the associated section:

I gave the folders in content a name without any special characters, which also excludes hyphens. The reason for this is that menus defined in Front Matter can’t contain these characters (only underscore). The file structure looks like this:

content/
  asection/ # NOT "a-section", as hyphens are not allowed
    subelement/bunch-of-files
    cover.jpg
    _index.htm
  anothersection/ # NOT "another-section"
    subelement/more-files
    subelement2/even-more-files
  cover.jpg
  _index.html
etc...  

Here is the Front Matter for one of my subelemens that belongs to a section:

title: This is a subelement
menu:
  asection: # name of the section above this subelement WITHOUT hyphens

Here is the code for my sidebar:

{{ $currentPage := . }}
{{ $currentSection := .Section }}

<ul class="site-sidebar-menu">
     {{ range index .Site.Menus $currentSection }}
     <li class="button{{ with $currentPage.IsMenuCurrent $currentSection . }} button-active{{- end -}}">
         <a href="{{ .URL }}">
         {{ .Pre }}
         {{ .Name }}
         </a>
     </li>
    {{ end -}}
</ul>

The magic happens with {{ range index .Site.Menus $currentSection }}, where $currentSection outputs asection and makes the string complete: .Site.Menus.asection.

This is a way to combine two (or more?) variables, or at least their output/values. I don’t fully understand how or why this works to combine one variable with another – if someone would like to try to explain this to me, please try!

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.