How do you display child pages specific to a section in a menu?

Hi all, I’m building out a documentation site which has a Main nav and Sidebar nav. After researching I’ve landed on building out my menu using the config file. The menus render correctly, but I’m stuck on how to render my sidebar navigation based on the section I’m in using the config file (see example below).

Here’s my config json. As you can see I’m calling out a single “main” menu, but using “parent” for navigation that would fall under the sidebar nav.

{
	"baseURL": "http://example.com/",
	"languageCode": "en-us",
	"title": "DS",
	"menu": {
		"main": [
			{
				"name": "Getting Started",
				"url": "/getting-started",
				"pageRef": "getting-started",
				"weight": 10
			},
			{
				"name": "Contents",
				"url": "/contents",
				"pageRef": "contents",
				"parent": "Getting Started"
			},
			{
				"name": "Download",
				"url": "/download",
				"pageRef": "download",
				"parent": "Getting Started"
			},
			{
				"name": "Foundations",
				"url": "/foundations",
				"pageRef": "foundations",
				"weight": 20
			},
			{
				"name": "Colors",
				"url": "/colors",
				"pageRef": "colors",
				"parent": "Foundations"
			},
			{
				"name": "Grid",
				"url": "/grid",
				"pageRef": "grid",
				"parent": "Foundations"
			},
			{
				"name": "Components",
				"url": "/components",
				"pageRef": "components",
				"weight": 30
			},
			{
				"name": "Alerts",
				"url": "/alerts",
				"pageRef": "alerts",
				"parent": "Components"
			},
			{
				"name": "Badges",
				"url": "/badges",
				"pageRef": "badges",
				"parent": "Components"
			},
			{
				"name": "Utilities",
				"url": "/utilities",
				"pageRef": "utilities",
				"weight": 40
			},
			{
				"name": "Background",
				"url": "/background",
				"pageRef": "background",
				"parent": "Utilities"
			},
			{
				"name": "Borders",
				"url": "/borders",
				"pageRef": "borders",
				"parent": "Utilities"
			}
		]
	}
}

Here’s my code for the Main nav which works great.

<header class="header">
	<nav class="header__nav">
		<div class="container header__nav-container">
			<div class="header__brand">
				<a href="{{ .Site.BaseURL }}" class="header__brand-type-link">{{ .Site.Title }}</a>
			</div>

			<ul class="header__nav-list">
				{{- $currentPage := . -}} 
				
				{{- range .Site.Menus.main -}}
				<li class="header__nav-item">
					<a href="{{ .URL }}" class='header__nav-link {{ if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}current_page_link{{end}}'>{{ .Name }}</a>
				</li>
				{{ end }}
			</ul>
		</div>
	</nav>
</header>

Here’s the code for my Sidebar nav. This would work great if I didn’t need the navigation to display based on the section you’re in. I have a feeling it has something to to with the .Children in my range. I tried methods like .Site.Section.Children, but that didn’t work. Any thoughts on what I’m missing here?

<nav class="sidebar__nav">
	<ul class="sidebar__nav-list">
		{{- $currentPage := . -}} 
		
		{{- range .Site.Menus.main -}}
			{{- if .HasChildren -}}
				{{- range .Children -}}
				<li class="sidebar__nav-item">
					<a href="{{ .URL }}" class='sidebar__nav-link {{ if $currentPage.IsMenuCurrent "main" . }}current_page_link{{end}}'>{{ .Name }}</a>
				</li>
				{{ end }}
			{{ end }}
		{{ end }}
	</ul>
</nav>

Anyone have thoughts on this? I’m really lost. The closest thing I could find was the use of range (index .Site.Menus $section), but the output is blank. I can’t seem to iterate over child pages of the individual sections.

<nav class="sidebar__nav">
	<ul class="sidebar__nav-list">
		{{- $currentPage := . -}} 
		{{- $section := $currentPage.Section -}} 
		{{- range (index .Site.Menus $section) -}}
				{{- range .Children -}}
				<li class="sidebar__nav-item">
					<a href="{{ .URL }}" class="sidebar__nav-link {{ if $currentPage.IsMenuCurrent `main` . }}current_page_link{{end}}">{{ .Name }}</a>
				</li>
				{{ end }}
		{{ end }}
	</ul>
</nav>
{{ range where site.Menus.main "Name" .CurrentSection.Title }}
  {{ range .Children }}
    <a href="{{ .URL }}">{{ .Name }}</a>
  {{ end }}
{{ end }}

When creating menu entries in site configuration, use pageRef for internal pages, and use url for external pages. Do not specify both.

6 Likes

Thank you so much for your help and extra advice. I really appreciate it. This works perfectly.

I have one follow up question that I had not considered until the menu started working. I have a rare case where I have two menu items named Colors but sit within different sections. I started looking at using identifier but does that mean I would need to add an identifier to each key/value in my config or just the two named Colors? Also, does that mean the {{ range where site.Menus.main "Name" .CurrentSection.Title }} would need to change to “Identifier” instead of “Name”?

First, make sure the pageRef values are not ambiguous by providing the full path.

Second, when two entries have the same name value, at least one of them must have a unique identifier value.

structure
content/
├── components/
│   ├── alerts.md
│   ├── badges.md
│   ├── colors.md
│   └── _index.md
├── foundations/
│   ├── colors.md
│   ├── grid.md
│   └── _index.md
├── getting-started/
│   ├── contents.md
│   ├── download.md
│   └── _index.md
├── utilities/
│   ├── background.md
│   ├── borders.md
│   └── _index.md
└── _index.md

config.json
{
  "baseURL": "https://example.com/",
  "languageCode": "en-us",
  "title": "Hugo Forum Topic #38845",
  "menu": {
    "main": [
      {
        "name": "Getting Started",
        "pageRef": "getting-started",
        "weight": 10
      },
      {
        "name": "Contents",
        "pageRef": "getting-started/contents",
        "parent": "Getting Started"
      },
      {
        "name": "Download",
        "pageRef": "getting-started/download",
        "parent": "Getting Started"
      },
      {
        "name": "Foundations",
        "pageRef": "foundations",
        "weight": 20
      },
      {
        "name": "Colors",
        "pageRef": "foundations/colors",
        "parent": "Foundations"
      },
      {
        "name": "Grid",
        "pageRef": "foundations/grid",
        "parent": "Foundations"
      },
      {
        "name": "Components",
        "pageRef": "components",
        "weight": 30
      },
      {
        "name": "Alerts",
        "pageRef": "components/alerts",
        "parent": "Components"
      },
      {
        "name": "Badges",
        "pageRef": "components/badges",
        "parent": "Components"
      },
      {
        "name": "Colors",
        "identifier": "x",
        "pageRef": "components/colors",
        "parent": "Components"
      },
      {
        "name": "Utilities",
        "pageRef": "utilities",
        "weight": 40
      },
      {
        "name": "Background",
        "pageRef": "utilities/background",
        "parent": "Utilities"
      },
      {
        "name": "Borders",
        "pageRef": "utilities/borders",
        "parent": "Utilities"
      }
    ]
  }
}


Example:

git clone --single-branch -b hugo-forum-topic-38845 https://github.com/jmooring/hugo-testing hugo-forum-topic-38845
cd hugo-forum-topic-38845
hugo server
2 Likes

This works perfectly. Thank you again for taking the time to describe how to reference pages and the correct usage of identifier in my scenario. And thank you for the Git repo. You’ve helped me get past a huge blocker.

1 Like

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