Is there a way of determining from within a template/partial whether the current page is the result of pagination? I’ve tried looking for the present of .Paginator.URL
, but that’s caused errors.
I haven’t needed to figure this out, but I did recall a similar idea being shared here before:
Relevant snippet:
{{- $siteTitle := .Site.Title -}}
{{ if ne .Kind "page" }}
{{ $pag := .Paginate (where .Data.Pages "Section" "blog") }}
<title>{{ .Site.Title }} {{ if $pag.HasPrev }}• Page {{ .Paginator.PageNumber }} of {{ .Paginator.TotalPages }}{{ end }}</title>
{{- else if .IsPage -}}
<title>{{ $title }} • {{ $siteTitle }}</title>
{{- end -}}
Which takes advantage of (Pagination | Hugo):
HasPrev
Whether there are page(s) before the currentHasNext
Whether there are page(s) after the current
Thanks, @maiki! This is semi similar to how I most recently tried which is using .Paginator.PageNumber
to determine if it’s greater than 1, however doing so seems to be creating pagination pages for those that shouldn’t. For instance, my home page now has localhost:1313/page/2/
.
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:
this was also a fight for me in the last 2 weeks…
Every page in paging should have different titles and descriptions, got this from an verifier back.
@bep
Can we have a .GetPager as page function? Give back null/nil if no pager is there.
here my changed list.html with page numbers, if anyone need it - must change the classes
{{ define "main" }}
<header>
{{ $pages := site.GetPage .Section }} {{ $paginator := .Paginate $pages.Pages 20}}
<h1><span>{{ site.Title | markdownify }}</span><i class="ph3 fas fa-dragon fa-fw"></i>{{ .Page.Title }} {{ $paginator.PageNumber }}</h1>
{{if isset .Params "description" }}<div class="f5 b w-90-ns pb1">{{ .Description }} {{ $paginator.PageNumber }}</div>{{end}}
</header>
<h2 class=dn>{{ .Page.Title }}</h2>
<article>
<div class=liste>
{{ range $paginator.Pages -}}
{{ .Render "summary" }}
{{- end }}
</div>
{{ partial "pagination" . }}
</article>
{{ end }}