collect all the pages where type: event {{- $cond1 := where .Site.RegularPages "Type" "event" }} {{- $events := $cond1 }}
from the result of 1 above, I would like to find the pages that have dateStartOfEvent set {{- $cond2 := where $events ".Params.datestartofevent" "!=" "nil" }}
from the result of 2 above, I would like to find the pages where dateStartOfEvent is after today {{- $cond3 := where $events (time .Params.dateStartOfEvent).After now }}
finally, iterate over the first 10 events and list them {{- $events_num := (.Site.Params.widgets.events_num | default 10) }} {{- range first $events_num $events }} ...
I am facing a problem in step 3 where I get the following error: <time .Params.dateStartOfEvent>: error calling time: unable to cast <nil> of type <nil> to Time. Why? In the previous filter $cond2 I had already (in theory) removed all the pages where dateStartOfEvent did not exist, so why is this error occuring?
Since I am super new to Hugo and golang, I would also love to know if there is a better and shorter (more idiomatic) way for doing the above? For example, in JS I would just chain a bunch of filters.
thanks for response. I am embarrassed about .After. I assumed that time.After would be an analog of time.Before (in the other direction), but I was wrong.
I looked at the example you linked, and that is pretty much exactly what I want to do. However, (in order to understand this better), I am still confused as to why my logic is not working. I now have the following
I still get the error <time .Params.dateStartOfEvent>: error calling time: unable to cast of type to Time
Shouldn’t $cond2weed out any pages where dateStartOfEvent doesn’t exist or is not set? (an aside: all my events pages do have a dateStartOfEvent, so actually $cond2is not even needed, but I am inserting it there just to future-proof the project just in case someone else creates and event page and forgets to add that param).
thanks for the hint. I followed your advice however the outcome is still the same
{{- $cond2 := where $events ".Params.datestartofevent" "ne" nil }}
{{- $events := $cond2 }}
{{- $cond3 := where $events (time .Params.dateStartOfEvent) "gt" now }}
{{- $events := $cond3 }}
the above croaks with <time .Params.dateStartOfEvent>: error calling time: unable to cast of type to Time. I also printed out the value of dateStartOfEvent, the param exists in all the pages in the range
<ul>
{{- range $events }}
<li>{{ printf "%#v" .Params.dateStartOfEvent }}]</li>
{{- end }}
</ul>
why is time .Params.dateStartOfEvent not casting the string to time in the where filter? Seems I am doing something fundamentally wrong and I have no idea what
just tried that but sorry, no luck. I get the same error as before
{{- $events := where .Site.RegularPages "Type" "event" }}
{{- $events := ($events.ByParam "datestartofevent") }}
{{- $events := where (time.Format "2006-01" .Params.dateStartOfEvent) "gt" now }}
execute of template failed: template: partials/widgets/events.html:5:26: executing "partials/widgets/events.html" at <time.Format>: error calling Format: unable to cast <nil> of type <nil> to Time
per the docs, the signature of the where function is
where COLLECTION KEY [optional OPERATOR] MATCH
maybe it is not possible to transform the key in line. I can’t figure out what is going on.
I did see that, thanks. Converting the frontmatter to TOML would involve going back to all the existing events pages and redoing the data. I will do that if I determine there is actually no way forward the way I am approaching the problem (that is, if inline transformation of keys is not possible in a where filter).
Unfortunately I can’t share the project repo as the project happens to be private, but really, it is a sum total of the following
{{/* 1. collect all the pages where type is event */}}
{{- $events := where .Site.RegularPages "Type" "event" }}
{{/* 2. from #1, find pages with "dateStartOfEvent" */}}
{{- $events := where $events ".Params.datestartofevent" "ne" nil }}
{{/* 3. from #2, find pages where "dateStartOfEvent" is after today */}}
{{- $events := where $events (time .Params.dateStartOfEvent) "gt" now }}
{{/* 4. finally, iterate over the first 10 events and list them */}}
{{- $events_num := (.Site.Params.widgets.events_num | default 10) }}
{{- range first $events_num $events }}
...
I always get the error on step 3. Interestingly, if I remove step 3 and put the same logic inside a range loop, I don’t get an error
{{- if $events }}
<ul>
{{- range $events }}
{{ if (isset .Params "datestartofevent") }}
{{ $t := (time .Params.dateStartOfEvent) }}
{{ if gt $t now }}
<li>{{ .Title }}</li>
{{- end }}
{{- end }}
{{- end }}
</ul>
{{- end }}
The above, however, produces a slightly different result from what I want to accomplish. Plus, I am really interested in understanding why I can’t get my initial approach to work
many thanks… this is exactly what I wanted|needed to know. Now I can look for alternative approaches. It might be worth adding this tidbit to the docs so others don’t go down the path I did
Another approach, if your custom dates are strings instead of TOML dates, is to perform a string comparison in the where clause, but this could get a little wobbly if your date formats are inconsistent or contain different offsets.
The comparison operators (eq, gt, ge, etc.) can be used with strings as well.
{{ range where (where site.RegularPages "Type" "event") "Params.datestartofevent" "ge" (now.Format "2006-01-02T15:04:05-07:00") }}
ok, thanks for the detailed advice. I might just bite the bullet and convert all my existing fm metadata to toml from the current yaml since I’d rather not do string comparisons of dates
Have a look at hugo convert toTOML . By default this is considered (correctly) unsafe, and will tell you it won’t do it without passing the --unsafe flag. Don’t do that.
Instead:
hugo convert toTOML -o /tmp/junk
Then examine the results. Dates will be quoted, but you can easily fix those after conversion in your IDE with a regex replace.