How do I call a function in a where clause? Or otherwise check if there's no elements satisfying a condition

What I’m trying to do is show elements, in this case meetings, that I store as markdown files, in three categories - this month, upcoming, and previous. That’s relatively easy when I enumerate over the collection three times like that:

{{ range .Pages }}
  {{ if lt ((time .Params.eventDate).Format "01.2006") (now.Format "01.2006") }}
     <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
  {{ end }}
{{ end }}

However, what I’d also like to do, is show a message like “No meetings this month” when there’s no meetings in a category. Here’s what I thought should work, but I can’t figure out how to call the time function in this syntax:

{{ range where .Pages (gt ((time .Params.eventDate).Format "01.2006") (now.Format "01.2006")) }}

Here’s the error I get:

execute of template failed at <time .Params.eventDate>: error calling time: unable to cast <nil> of type <nil> to Time

Putting “” around .Params.eventDate doesn’t work either, then it says it can’t call time on this string. If I can figure out how to filter those events in the where clause, I suppose I can then assign the result to a variable and check the length somehow.

Is your front matter TOML or YAML? It makes a difference…

With TOML, date values are first-class citizens. TOML has a date data type while JSON and YAML do not. When you add a custom date field to your TOML front matter, the value is already of type time.Time and does not require conversion.

1 Like

It’s YAML, but if it helps I can change to TOML or JSON. I could also use date in YAML, which I think is also automatically time type, but then the posts greater than current time won’t show at all. Also, I’m not sure if that’s the solution, as in the if clause it works perfectly - would it make a difference in a where clause?

Yes, the predefined front matter dates are always cast to time.Time values, regardless of front matter format:

date: 2022-01-01T17:39:56-08:00
publishDate: 2022-02-01T08:00:00-08:00
expiryDate: 2023-02-01T08:00:00-08:00
lastmod: 2022-01-28T17:37:06-08:00

This example might be helpful; it describes comparison of custom date fields with respect to front matter format.

I figured out a solution, or rather ChatGPT figured out a solution for me that I had to modify slightly:

{{ $eventsThisMonth := slice }}
{{ $eventsUpcoming := slice }}
{{ $eventsPrevious := slice }}

{{ range .Pages }}
    {{ $eventDate := .Params.eventDate }}
        {{ $parsedDate := (time $eventDate).Format "01.2006" }}
        {{ if gt $parsedDate (now.Format "01.2006") }}
            {{ $eventsUpcoming = $eventsUpcoming | append . }}
        {{ else if eq $parsedDate (now.Format "01.2006") }}
            {{ $eventsThisMonth = $eventsThisMonth | append . }}
        {{ else }}
            {{ $eventsPrevious = $eventsPrevious | append . }}
        {{ end }}
{{ end }}

{{ if $eventsThisMonth }}
    <h2>This Month</h2>
    {{ range $eventsThisMonth }}
        <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
    {{ end }}
{{ else }}
    <p>No meetings this month</p>
{{ end }}

{{ if $eventsUpcoming }}
    <h2>Upcoming</h2>
    {{ range $eventsUpcoming }}
    <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
    {{ end }}
{{ else }}
    <p>No upcoming meetings</p>
{{ end }}

{{ if $eventsPrevious }}
    <h2>Previous</h2>
    {{ range $eventsPrevious }}
    <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
    {{ end }}
{{ else }}
    <p>No previous meetings</p>
{{ end }}

It’s much more complicated code than what calling a function in a where clause would allow, but it works.

The ChatGPT approach is broken; it classifies “2024-04-02” as a past event.

If you use unquoted dates in your TOML front matter you can do date (not string) comparisons in your where clauses:

{{/* First day of current month */}}
{{ $fdocm := time.AsTime (printf "%d-%d-01" now.Year now.Month) }}

{{/* First day of next month */}}
{{ $fdonm := $fdocm.AddDate 0 1 0 }}

{{ $eventsPrevious := where .Pages "Params.eventDate" "lt" $fdocm }}
{{ $eventsUpcoming := where .Pages "Params.eventDate" "ge" $fdonm }}
{{ $eventsThisMonth := .Pages | complement $eventsPrevious $eventsUpcoming }}

{{ with $eventsThisMonth.ByParam "eventDate" }}
  <h2>This Month</h2>
  {{ range . }}
    <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
  {{ end }}
{{ else }}
  <p>No meetings this month</p>
{{ end }}

{{ with $eventsUpcoming.ByParam "eventDate" }}
  <h2>Upcoming</h2>
  {{ range . }}
    <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
  {{ end }}
{{ else }}
  <p>No upcoming meetings</p>
{{ end }}

{{ with $eventsPrevious.ByParam "eventDate" }}
  <h2>Previous</h2>
  {{ range . }}
    <p class="fw-bolder fs-5 m-0 lh-1">{{ .Params.name }}</p>
  {{ end }}
{{ else }}
  <p>No previous meetings</p>
{{ end }}
2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.