How to select a specific menu in navigation template [SOLVED]

I am trying to implement a global switch for the main navigation. This needs to be able to switch between different versions.

I have menus defined for each version of the documentation (v1, v2). Parameters define the menu names and the default menu.

config.toml

[params]
    menuNames = ["v1", "v2"]
    menuname = "v2"

[[menu.v1]]
    name = "Getting Started"
    identifier = "getting-started"
    weight = 1000

[[menu.v2]]
    name = "Getting Started"
    identifier = "getting-started"
    weight = 1000

content

/content/docs/v1/getting-started/introduction.md

+++
title = "Introduction"
linktitle = "Introduction"
weight = 10
menuname = "v1"
[menu.v1]
    parent = "getting-started"
+++
intro version 1

/content/docs/v2/getting-started/introduction.md

+++
title = "Introduction"
linktitle = "Introduction"
weight = 10
menuname = "v2"
[menu.v1]
    parent = "getting-started"
+++
intro version 2

I having problems getting the default navigation.html partial template to work. It looks like this

<ul>
{{ $menuname := $.Param "menuname" }}
{{ $.Scratch.Add "menuname" $menuname }}
{{ $.Scratch.Add "menu" .Site.Menus.v1 }}
{{ if eq ($.Scratch.Get "menuname") "v2" }}
    {{ $.Scratch.Set "menu" .Site.Menus.v2 }}
{{ end }}
{{ $currentNode := . }}{{ range ($.Scratch.Get "menu") }}{{ if .HasChildren }}
  <li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}
    <ul>{{ range .Children }}
      <li{{ if $currentNode.IsMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}><a href="{{ .URL }}">{{ .Name }}</a></li>{{ end }}
    </ul>
  </li>{{ else }}
  <li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}</li>{{ end }}
{{ end }}
</ul>

I am trying to get the $menuname from either the .Page or .Site {{ $menuname := $.Param "menuname" }} and getting error <$.Param>: Param is not a field of struct type *hugolib.Page in theme/partials/navigation.html

Then I want to select the menu based on the name, and add it to .Scratch (variables didn’t work). Finally render the menu items by iterating the selected menu.

Apart from the wrong usage of the $.Param function, would this approach work?

I did manage to get it to work by repeating the range portion for each distinct menu, but that seemed like a lot of repetition.

I am probably missing an simple way of getting the range command to work with a dynamically selected menu like

{{ range .Site.Menus.{{$.Param "menuname"}} }}

which doesn’t work.

Any advice appreciated.


Using the .Scratch for the menuname as below works

  <ul>
  {{ $.Scratch.Add "menuname" .Site.Params.menuname }}
  {{ if isset .Params "menuname" }}
    {{ $.Scratch.Set "menuname" .Params.menuname }}
  {{ end }}
  {{ $.Scratch.Add "menu" .Site.Menus.v1 }}
  {{ if eq ($.Scratch.Get "menuname") "v2" }}
    {{ $.Scratch.Set "menu" .Site.Menus.v2 }}
  {{ end }}
  {{ $currentNode := . }}{{ range ($.Scratch.Get "menu") }}{{ if .HasChildren }}
    <li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}
      <ul>{{ range .Children }}
        <li{{ if $currentNode.IsMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}><a href="{{ .URL }}">{{ .Name }}</a></li>{{ end }}
      </ul>
    </li>{{ else }}
    <li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}</li>{{ end }}
  {{ end }}</ul>

However that does not seem very elegant. Am I missing an alternative?

Upgrading hugo to .0.15 sorted that out. Now the below works.

<ul>
{{ $menuname := $.Param "menuname" }}
{{ $.Scratch.Add "menuname" $menuname }}
{{ $.Scratch.Add "menu" .Site.Menus.v1 }}
{{ if eq ($.Scratch.Get "menuname") "v2" }}
   {{ $.Scratch.Set "menu" .Site.Menus.v2 }}
{{ end }}
{{ $currentNode := . }}{{ range ($.Scratch.Get "menu") }}{{ if .HasChildren }}
 <li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}
   <ul>{{ range .Children }}
     <li{{ if $currentNode.IsMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}><a href="{{ .URL }}">{{ .Name }}</a></li>{{ end }}
   </ul>
 </li>{{ else }}
<li{{ if $currentNode.HasMenuCurrent ($.Scratch.Get "menuname") . }} class="is-active"{{ end }}>{{ .Name }}</li>{{ end }}     {{ end }}
</ul>

With the help of the example in https://discuss.gohugo.io/t/hugo-multisite-workflow/103/16 I managed to get a tidier solution

  <ul>{{ $menu := index ( index $.Site.Menus  ($.Param "menuname") ) }}{{ $currentNode := . }}{{ range $menu }}{{ if .HasChildren }}
    <li{{ if $currentNode.HasMenuCurrent ($.Param "menuname") . }} class="is-active"{{ end }}>{{ .Name }}
      <ul>{{ range .Children }}
        <li{{ if $currentNode.IsMenuCurrent ($.Param "menuname") . }} class="is-active"{{ end }}><a href="{{ .URL }}">{{ .Name }}</a></li>{{ end }}
      </ul>
    </li>{{ else }}
    <li{{ if $currentNode.HasMenuCurrent ($.Param "menuname") . }} class="is-active"{{ end }}>{{ .Name }}</li>{{ end }}
  {{ end }}</ul>