Rewrite recursive menu code with ancestors?

Edit: My problem is solved. See the 3rd iteration below. Many thanks to @bep for his work on Hugo and the addition of .Ancestors :slight_smile:

I am trying to create a recursive menu:

  • It takes the pure structure of hugo (_index.md existing in each directory)
  • The navigation must be “opened” on the current page and “closed” elsewhere.
  • The sub-pages of the current page are displayed.
  • The sections and pages at the roots are always present

I have a template that works well.

The partial template creates a recursive hierachical menu which is opened on the current page:

{{ define "subpages" }}
{{ $thePage := .currentPage }}
<ul>
    {{ range .context.Pages }}
    <li>
        
        <a href="{{ .RelPermalink }}">{{ .RelPermalink }}</a>
        {{ if in $thePage.Permalink .Permalink }}
            {{ template "subpages" (dict "context" . "currentPage" $thePage ) }}
        {{ end }}
    </li>
    {{ end }}
</ul>
{{ end }}


{{ $thePage := .Page }}
<ul>
{{ range site.Pages }}
{{ if eq (len .Ancestors) 1 }}
<li>
    <a href="{{ .RelPermalink }}">{{ .RelPermalink }}</a>
    {{ if in $thePage.Permalink .Permalink }}
        {{ template "subpages" (dict "context" . "currentPage" $thePage ) }}
    {{ end }}
</li>
{{ end }}
{{ end }}
</ul>

To test if hugo should go further in the hierarchy, I test the permalinks:

{{ if in $thePage.Permalink .Permalink }}

I’m pretty sure it must be possible to make a simpler test with the .Ancestors variable. I already use this variable to test if pages are at the root of the site.

My “challenge”: can we rewrite the condition more simply? Or, better, can we factor all the code of this partial in a better way.

Thanks for all your advice.

There is a viable version of this menu in the branch:

The night brings advice. Found the solution to avoid URL by URL comparisons. It is now possible to use non-hierarchical URLs but keep the menu structure.

The solution was simple. Reread the doc in detail to list all possible page variables. And find .IsAncestor.

I feel like I’m going to reread every page of Hugo’s doc. Which I haven’t done for too long.

The new code:

{{ define "subpages" }}
    {{ $thePage := .currentPage }}
    <ul>
        {{ range .context.Pages }}
            <li>
                <a href="{{ .RelPermalink }}">{{ .RelPermalink }} </a>
                {{ if or (.IsAncestor $thePage) (eq . $thePage) }}
                    {{ template "subpages" (dict "context" . "currentPage" $thePage ) }} 
                {{ end }}
            </li>
        {{ end }}
    </ul>
{{ end }}


{{ $thePage := .Page }}

<ul>
    {{ range site.Pages }}
        {{ if eq (len .Ancestors) 1 }}
            <li>
                <a href="{{ .RelPermalink }}">{{ .RelPermalink }}</a>
                {{ if or (.IsAncestor $thePage) (eq . $thePage) }}
                    {{ template "subpages" (dict "context" . "currentPage" $thePage ) }}
                {{ end }}
            </li>
        {{ end }}
    {{ end }}
</ul>

To close this topic, a rewrite of the last proposed file. Instead of listing the pages and sections at the root, I set the context at the home page. And I launch the recusivity.:

 {{ define "subpages" }}
    {{ $thePage := .currentPage }}
    <ul>
        {{ range .context.Pages }}
            <li>
                <a href="{{ .RelPermalink }}">{{ .RelPermalink }} </a>
                {{ if or (.IsAncestor $thePage) (eq . $thePage) }}
                    {{ template "subpages" (dict "context" . "currentPage" $thePage ) }} 
                {{ end }}
            </li>
        {{ end }}
    </ul>
{{ end }}


{{ $thePage := .Page }}
{{ $context := .GetPage "/" }}
{{ template "subpages" (dict "context" $context "currentPage" $thePage ) }}

With Hugo > 0.111 and the global page function:

{{ define "subpages" }}
    <ul>
        {{ range .Pages }}
            <li>
                <a href="{{ .RelPermalink }}">{{ .Title }}</a>
                {{ if or (.IsAncestor page) (eq . page) }}
                    {{ template "subpages" . }} 
                {{ end }}
            </li>
        {{ end }}
    </ul>
{{ end }}


{{ $context := .GetPage "/"}}
{{ template "subpages" $context }}

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