Paginating future content (events)

I’m trying to create a paginated list of upcoming events. Since I’m doing pagination, I can’t just range over ALL events and include a nested if statement, because I’ll get an empty pagination page if the events are in the past. I currently have ten events that are in the future. I’m running Hugo version 55.6.

The start date/time for an event is stored in a frontmatter parameter called start.

Frontmatter example:

---
title: 'Seniors Fishing Rodeo'
start: 2020-06-05T09:00:00.000Z
end: 2020-06-05T12:00:00.000Z
---

Here’s what I’ve tried:

Attempt:
{{ $futureContent := where .Site.RegularPages (time .Params.start).Unix “ge” now.Unix }}

Result:

Failed to render pages: render of "section" failed: template: events/list.html:1:250: executing "events/list.ace::main" at <.Params.start>: can't evaluate field Unix in type *errors.errorString

Attempt:
{{ $futureContent := where .Site.RegularPages “.Params.start” “ge” now }}

Result:
Fails silently – no errors, no results returned

Attempt:

{{ .Scratch.Set "futureContent" slice }}
{{ range where .Site.RegularPages "Section" "events" }}
      {{ if ge (time .Params.start).Unix now.Unix }}
          {{ .Scratch.Add "futureContent" (slice .) }}
      {{ end }}
{{ end }}

Result:
{{ .Scratch.Get }} is empty

I found this older topic that suggested some of these solutions, but never came to a resolution.

Add {{ printf "%#v" (time .Params.start).Unix }} inside of the range, does it print the timestamp or an error? My guess is that the time can not be parsed properly. (It’s a guess, sorry :wink: )

The error says that the issue is right there, at the point where you try to use .Unix to convert a text into a unix timestamp.

What happens if you remove the Z at the end of the time?
What happens if you replace the Z at the end of the time with +00:00?

Instead of now.Unix just try now

This works. For the August fly fishing event I get: 15593796001565690400

If I remove the Z from the timestamp or replace it with +00:00 it’s automatically reinserted when I save the file. I’m not sure if Hugo is doing that or some other file watcher I have running.

Didn’t I try that with my second attempt?

{{ $futureContent := where .Site.RegularPages “.Params.start” “ge” now }}

Ah, missed that. So building off of that, what if you formatted the dates the same before comparing, something like:

.Format "2006-01-02T15:04:05"

Where would I do the .Format? I gave this a shot below, but got an error back. Let me know if you intended me to try something else!

{{ $futureContent := where .Site.RegularPages (.Format ".Params.start") "ge" now }}

Failed to render pages: render of "section" failed: template: events/list.html:1:238: executing "events/list.ace::main" at <.Format>: can't evaluate field Format in type *hugolib.pageState

Had this in mind:

{{ .Scratch.Set "futureContent" slice }}

{{ $date_format := "2006-01-02T15:04:05" }}

{{ range where .Site.RegularPages "Section" "events" }}
  {{ $formatted_start := (time .Params.start).Format $date_format }}
  {{ $formatted_now := now.Format $date_format }}

  {{ if ge $formatted_start $formatted_now }}
      {{ .Scratch.Add "futureContent" (slice .) }}
  {{ end }}
{{ end }}

Thanks for the suggestion!

I’m trying to avoid nesting an if statement inside of my range because I’m paginating the results. If 10 of my 20 events are in the past then the first page of results will still be included in the Pager, but they’ll be blank since they don’t meet the criteria of the if statment.

Ideally I would be able to filter out all of the past events before passing that data into a range to properly support pagination.

Ah. I thought that is what you were doing by adding those pages to a slice, and then paging the slice.

My thought was, if I were using Scratch, I could build the slice then range over it.

You could even do it without Scratch:

{{ $future_content := slice }}

{{ $date_format := "2006-01-02T15:04:05" }}

{{ range where .Site.RegularPages "Section" "events" }}
  {{ $formatted_start := (time .Params.start).Format $date_format }}
  {{ $formatted_now := now.Format $date_format }}

  {{ if ge $formatted_start $formatted_now }}
    {{ $future_content = $future_content | append . }}
  {{ end }}
{{ end }}

{{ range $future_content }}
  {{ . }}
{{ end }}

Then replace that last range with your pageinator code.

1 Like

Thanks for your suggestions, @zwbetz! I simplified things a bit to use .Unix rather than a prescriptive $date_format. This does seem to be a little bit more difficult than it should have been, but alas, a solution:

{{ $futureContent := slice }}
{{ range sort (where .Site.RegularPages "Section" "events") ".Params.start" }}
  {{ if ge (time .Params.start).Unix now.Unix }}
    {{ $futureContent = $futureContent | append . }}
  {{ end }}
{{ end }}

{{ range $futureContent }}
   {{ .Render "summary" }}
{{ end }}
1 Like