Sort pages by a value stored in scratch?

Hello,

I’m trying to sort a set of pages by a value I set in the pages’ Scratch variable and not having any luck :frowning:

To give a bit more context ~

My template has a bunch of boolean values that I’m summing into the pages’ scratch as a variable I’m calling score.

I can see that score is set properly with the following:

{{ .Scratch.Get "score" }} ~ returns a number (score) eg: 1,3,4, whatever

Now I need to sort pages by this score but I’m having no luck.

I’ve tried ~

Using byParam:

{{ range $pages.byParam (.Scratch.Get "score") }}

Doesn’t work because I think this would try to sort by a param named 1,2,3 etc…

Using sort:

{{ range sort $pages (.Scratch.Get "score") }}

Again, same thing… I’m thinking it’s looking for a param that doesn’t exist.

Creating a map in Scratch and sorting the map:

$.Scratch.SetInMap "pages" (.Scratch.Get "score") .
$pages := $.Scratch.GetSortedMapValues "pages"

This sort of works ~ I get back ordered pages that I can sort but since I’m using the score as the key and multiple items have the same score I’m overwriting some of the values. I can continue to explore this avenue but it seems very complicated.

This seems like it shouldn’t be so hard, but maybe I’m missing something? Is there a way to sort pages by a compile time calculated value?

In your single page template do something like:

{{ .Store.Add "counter" $someNumber }}

The .Store method is similar to .Scratch, with the same methods, but the stored values survive page rebuilds when running hugo server.

In your list template, we’re going to iterate through the pages twice.

{{ $s := slice }}
{{ range site.RegularPages }}
  {{ $s = $s | append (dict "counter" (.Store.Get "counter") "page" .) }}
{{ end }}

This will build a slice of maps, with this data structure:

[
  {
    "counter": 15,
    "page": {
      "Content": "",
      "Plain": "",
      ...
    }
  },
  {
    "counter": 6,
    "page": {
      "Content": "",
      "Plain": "",
      ...
    }
  }
]

Now we iterate through the slice of maps, sorting by counter in either ascending (“asc”) or descending (“desc”) order. The default is ascending order.

{{ range sort $s "counter" "desc" }}
  <h2><a href="{{ .page.RelPermalink }}">{{ .page.Title }}</a></h2>
  <div>{{ .page.Store.Get "counter" }}</div>
{{ end }}
1 Like

Thank you for the clear explanation! That did the trick and helped me get a little more familiar with Hugo templating. I really appreciate it!

1 Like

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