Sorting Menu by weight and reversed

Sorry, for reopening this issue, but I’ve a similar problem with my navigation. It has sub items (with parent in front matter) and using weight to define the order.

I need to render the menu twice - one reversed - and that list is always strange when I hit a sub menu item.

 <nav class="header-nav desktop">
  <ul class="nav-lvl1" >
{{ $currentPage := . }}
{{ range .Site.Menus.main.ByWeight.Reverse }}
{{ if .HasChildren }}
   <li>
    <a href="{{ .URL }}" class=" onlymobile"><span class="plussign">+</span><span class="minussign" style="display:none;">-</span>&nbsp;&nbsp;</a>
    <a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a>
    <ul class="nav-lvl2">
{{ range .Children }}
     <li><a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a></li>
{{ end }}
    </ul>
   </li>
{{ else }}
   <li><a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }} active{{end}}" link>{{ .Name }}</a></li>
{{ end }}
{{ end }}
  </ul>
 </nav>
 <nav class="header-nav mobile">
  <ul class="nav-lvl1" >
{{ range .Site.Menus.main.ByWeight }}
{{ if .HasChildren }}
   <li>
    <a href="{{ .URL }}" class=" onlymobile"><span class="plussign">+</span><span class="minussign" style="display:none;">-</span>&nbsp;&nbsp;</a>
    <a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a>
    <ul class="nav-lvl2">
{{ range .Children }}
     <li><a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a></li>
{{ end }}
    </ul>
   </li>
{{ else }}
   <li><a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a></li>
{{ end }}
{{ end }}
  </ul>
 </nav>

I’m using byWeight as sorting and so it should work, but everytime I hit a submenu entry the menu in desktop mode (reversed) is re-sorted. Sometimes items are twice or so. In normal order (mobile) everything is ok. I’ve tried to store the menu in a var, but it has similar effects.

1 Like

Hi there,

I’ve moved your question to its own topic.

It would be easier to help you if you had your code in a repo we can replicate. Please have a read about Requesting Help .

No problem - I’ve created a repo under https://github.com/trickert76/hugo-menu-demo

You can run the demo with ‘hugo server’ and when you click thru the menu at the top right, the menu item changes. It is reproducable with desktop view (which is reverse order) in mobile view (reduce the browser) the mobile menu is always correct.

Is this what you want to accomplish? I changed your menu weight to be positive, and to increment by 10, so Menu1 is 10 and so forth. But Home has a weight of 100.

Now I think I got what you meant, I think you are having the same problem described here:

I recorded a quick .gif showing the menu changing order on each page (on desktop). So other people will understand it better.

menu

The above behavior is the wrong one. The solution, as presented by @moorereason on the thread I linked, is to sort the menu by weight to get is reversed order, like so:

{{ $currentPage := . }}
 <nav class="header-nav desktop">
  <ul class="nav-lvl1" >
  {{ range .Site.Menus.main.Sort.ByWeight }}
  {{ if .HasChildren }}
        <li>
          <a href="{{ .URL }}" class="{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }}active{{end}}" link>{{ .Name }}</a>

Hi,

First - you’re funny. My first post was a reply to the given post and then @pointyfar moved my reply to a new post and now you’re refering to the “original” post. I know, you can’t know, but it’s …funny.

Second - sorry, I made a mistake in the Git repo. As you can see in my first post, it was ’ .Site.Menus.main.ByWeight.Reverse. Of course I tried it with .Site.Menus.main.Sort.ByWeight.Reverse which has no effect (double sorting, first sort by internal parameters and then by weight). The content in the repo was my last trial yesterday.

I’ve updated the repo.

The behaviour now is ok on first level, and when you click on the first submenu item, sometimes also fine (Menu3/). But when you click on the second submenu item (or the third one), the top level is corrupted (Menu1/, Menu2/*).

Addon: And that is really only the .Reverse-function. When I remove it, the order is always the same, whatever item I click.

Sorry about the confusion! :slight_smile:
Well, on my local version here, this secondary behavior issue didn’t occur, so maybe is a matter of Hugo version AND/OR the negative weights you used? Remember: I changed the weights to be positive.

I am using Hugo Static Site Generator v0.74.1/extended windows/amd64

See another gif showing that the menus don’t change when I click.

Hmm, that is strange. Maybe it’s because you changed the weight. But did you try it with .Reverse order? I’m using the MacOS homebrew version 0.74.3/extended. And both the “hugo server” version and the generated HTML version producing wrong output (in case of .Reverse ordering!). Be aware that the correct order would be HOME,Menu1,Menu2,Menu3,Menu4. Maybe the situation with subitems has a problem to.

I’ve changed the CSS now in my private project and the flow is now left to right and so I’ve a workaround for the problem.

Which screen2gif tool did you use? So I can create a video of it.

Apologies for the confusion, we generally discourage reviving old topics, as often the participants are no longer active. Hugo development also moves very fast, so usually the old discussion is no longer relevant.


As to the question: I am able to replicate this on a much simpler setup, repo here: https://github.com/pointyfar/hugo-menu-issue-27710

I believe this to be potentially a bug and I would recommend reporting to the issue tracker.

The expected result with

index / weight / name / page
{{ range $k, $v := .Site.Menus.main.ByWeight }}
    {{ $k }} / {{ $v.Weight }} / {{ $v.Name }} / <a href="{{.URL}}">{{ $v.Page }}</a>
    <br>
{{ end }}

should be the following:

index / weight / name / page
0 / 10 / A / Page(/posts/A.md)
1 / 20 / B / Page(/posts/B.md)
2 / 30 / C / Page(/posts/C.md)
3 / 40 / D / Page(/posts/D.md)
4 / 50 / E / Page(/posts/E.md)
5 / 100 / Home / Page(/_index.md)

However occasionally I would get results as below:

0 / 10 / A / Page(/posts/A.md)
1 / 20 / B / Page(/posts/E.md)
2 / 40 / D / Page(/posts/D.md)
3 / 30 / C / Page(/posts/C.md)
4 / 20 / B / Page(/posts/B.md)
5 / 10 / A / Page(/posts/A.md)  <-- appears twice, missing /_index.md
0 / 50 / E / Page(/posts/E.md)
1 / 30 / C / Page(/posts/C.md)
2 / 30 / C / Page(/posts/C.md)  <-- appears twice, missing D.md
3 / 100 / Home / Page(/_index.md)
4 / 10 / A / Page(/posts/A.md)
5 / 20 / B / Page(/posts/B.md)

I am able to reproduce up to at least Hugo version 0.55

1 Like

Nice.

I’m able to intermittently reproduce the behavior when building from latest source, using either hugo or hugo server. I had to run hugo several times in a row to see the problem.

When the output is incorrect, it appears to be randomly incorrect (i.e., my incorrect output is different than your incorrect output).

When I run HUGO_NUMWORKERMULTIPLIER=1 hugo I am unable to reproduce the problem (I ran 50 builds in a row). This appears to be a concurrency issue.

When I run HUGO_NUMWORKERMULTIPLIER=4 hugo I am able to reproduce the problem intermittently, but sometimes it might not occur for 40 or more runs.

1 Like

Yes, that is my observation as well. Also, it is occasionally randomly incorrect across pages, in the same run, i.e. /posts/A/ would have the correct result, but not /posts/B/.

Didn’t know bout this, thanks.

I’m using https://github.com/NickeManarin/ScreenToGif, it’s feature-packed, but it’s Windows only.

@pointyfar

I would be happy to create a GitHub issue. Do you intend to keep https://github.com/pointyfar/hugo-menu-issue-27710, or is this repository temporary? I’m fine either way, just let me know.

Feel free to create the issue, I’m happy to keep the repo up.

Will do. Please merge the PR with the test script. Thanks.

2 Likes

Thanks a lot.

A deeper look into the Go-code tells me, that this is strange:

// Reverse reverses the order in Pages and returns a copy.
//
// Adjacent invocations on the same receiver will return a cached result.
//
// This may safely be executed  in parallel.
func (p Pages) Reverse() Pages {
  const key = "pageSort.Reverse"

  reverseFunc := func(pages Pages) {
	for i, j := 0, len(pages)-1; i < j; i, j = i+1, j-1 {
		pages[i], pages[j] = pages[j], pages[i]
	}
  }

  pages, _ := spc.get(key, reverseFunc, p)

  return pages
}

Is this for-loop a good idea?