UPDATE
The paginator partial template file at the end of this post includes a line of code that is commented out yet is necessary for Hugo to render the page correctly. That is confusing and undesirable. This issue was addressed and corrected in a later post.
Background
This project is built with Hugo and uses the Minimal Hugo theme.
This post is part of an ongoing effort to tailor the theme over time.
Objective
In a previous post we built a new user interface for navigating between list pages. But the approach used in that post seems to go against the general Hugo structure for automatically creating list pages, so it introduced several problems.
Most strikingly, list pages for subsections always displayed a count for, and pointed to, the list page for all posts. That presented confusing and unhelpful results for subsection list pages.
In this post we’ll update the interface to display correct and relevant information for all sections and subsections.
Building the solution
As mentioned, the biggest problem with the previous design is that it seemed to fight against the default list structure used by Hugo because it tried to create two list pages in different forms while Hugo only natively generates one. In order to make things simpler, and, more importantly, correctly functioning, we’ll return to a design with only one list page.
Step 0: Original code
The original list page layout that shipped with the Minimal theme worked reliably for all sections and subsections and it is close to the desired user interface, so we’ll use that as our starting point.
The code for creating list pages for this project is located in the list.html file of the /layouts/_default/ directory. The original version is below:
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
{{ range (.Paginator 5).Pages }} {{ partial "list-item" . }} {{ end }}
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
Step 1: Refactoring
We’ll make a minor change to refactor the code for readability.
The altered lines are highlighted.
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
{{ range (.Paginator 5).Pages }}
{{ partial "list-item" . }}
{{ end }}
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
Step 2: Updating the appearance
We’ll add horizonal lines to visually separate the list.
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
<hr>
{{ range (.Paginator 5).Pages }}
{{ partial "list-item" . }}
{{ end }}
<hr>
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
Step 3: Updating the Paginator range
The most substanitive change is including more posts on a single list page.
We can accomplish that by setting the pagination value to a large number, like 1000. That will most likely allow all posts to be listed on a single page while providing the fallback of generating a paginated list if the number of posts exceeds 1000.
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
<hr>
{{ range (.Paginator 1000).Pages }}
{{ partial "list-item" . }}
{{ end }}
<hr>
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
Step 4: Adding the count of total posts
Now, we’ll add a count of all the posts for a section.
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
<h5>{{ .Paginator.NumberOfElements }} total posts</h5>
<hr>
{{ range (.Paginator 1000).Pages }}
{{ partial "list-item" . }}
{{ end }}
<hr>
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
But this creates a problem.
It’s not clear why, but this additional line causes Hugo to ignore the paginator value of 1000 and return to using the default value of 10.
We could resolve that issue by moving this new line below our call to .Paginator, but that isn’t the layout we want.
There is a workaround for this problem.
Step 5: Fixing the paginator value
While we don’t want to move the actual .Paginator call to a different line, we can add a non-functional call.
If we add a new .Paginator call at the top of the page and comment it out it won’t actually appear on the page, but Hugo will still use it to set the paginator value to 1000.
<!-- INCLUDE THIS LINE AT THE TOP SO THE PAGINATOR CORRECTLY SETS THE PAGINATION VALUE: {{ range (.Paginator 1000).Pages }} {{ partial "list-item" . }} {{ end }} -->
{{ partial "header" . }}
<main>
<h2>{{ .Title }}</h2>
<h5>{{ .Paginator.NumberOfElements }} total posts</h5>
<hr>
{{ range (.Paginator 1000).Pages }}
{{ partial "list-item" . }}
{{ end }}
<hr>
</main>
{{ partial "paginator" . }}
{{ partial "footer" . }}
It’s ugly and non-intuitive, but it works.
Conclusion
It isn’t desirable to have a commented line impacting the way pages are rendered, and it’s not clear why it works, but it does for now.
There are likely more elegant solutions for this design challenge, but it was more important to first get list pages working as expected. Now, at least, they do.