Setup
layouts/_default/
├── baseof.html <-- in here, before the main block, you want to know if the current page is a pager, and if so, which pager?
├── home.html
├── list.html <-- in here you do {{ range (.Paginate .Pages 5).Pages }}
└── single.html
Logical but flawed approach
A logical but flawed approach is to place something like this in baseof.html
{{ with .Paginator }}
Current pager number: {{ .PageNumber }}
{{ end }}
And there are many posts in this forum where site authors have tried this, only to later discover the unpleasant side effects.
Unpleasant side effects in this example
1) We inadvertently paginated the home page.
2) Our list page won’t show 5 pages per pager, but will instead use the paginate
site configuration value (default is 10).
Why does this happen?
Because both the .Paginate
and .Paginator
methods cause pagination to occur, and the first one to be invoked wins.
https://gohugo.io/templates/pagination/#list-paginator-pages
If you call
.Paginator
or.Paginate
multiple times on the same page, you should ensure all the calls are identical. Once either.Paginator
or.Paginate
is called while generating a page, its result is cached, and any subsequent similar call will reuse the cached result. This means that any such calls which do not match the first one will not behave as written.
What should we do?
It would be great if the .Paginator
method did not cause pagination to occur, but instead simply gave you access to the properties once pagination has occurred (e.g., .PageNumber
, .HasPrev
, .HasNext
, etc.). This may not be possible due to concurrency or the rendering sequence.
That’s probably worthy of a GitHub issue, and definitely a breaking change, but in my view worth the trouble given how often this problem arises.
What can we do right now?
In our example, let’s place this in list.html
{{ range (.Paginate .Pages 5).Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2>
{{ end }}
{{ template "_internal/pagination.html" . }}
{{ .Store.Set "paginator_number_of_pagers" .Paginator.TotalPages }}
Now, in baseof.html we can reliably retrieve the number of pagers (which might be just 1) with:
{{ with .Store.Get "paginator_number_of_pagers" }}
Number of pagers: {{ . }}
{{ end }}
I emphasize reliably because, due to concurrency, other useful paginator properties such as .PageNumber
cannot be passed reliably using a .Store
or .Scratch
.
OK, great, so we know how many pagers, but what we really want to know is, which pager?
We cannot parse the .RelPermalink
due to this issue, so we need to take a different approach: