Determine if current page is result of pagination

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:

3 Likes