Hugo

Sort by custom date parameter

Hi, i have a headless history-item content type, which i use to display on a timeline. The following code does not throw up any errors, but the sort function, which is meant to order the content according to my historicalDate parameter, is ignored:

{{ with .GetPage "/about/history/index.md" }}
  {{ with .Resources.ByType "page" }}
    {{ range sort . ".Params.historicalDate" }}
      Content here should be ordered by date.
    {{ end }}
  {{ end }}
{{ end }}

It doesn’t matter what date i include in the historicalDate front matter, the content does not sort. For example, here’s a simplified snapshot at the front matter from three different files:

---
title: Historical item 1
historicalDate: 2019-07-01T00:00:00-04:00

---
Content.
---
title: Historical item 2
historicalDate: 2011-06-27T13:32:36-04:00

---
Content.
---
title: Historical item 3
historicalDate: 2012-06-27T13:32:36-04:00

---
Content.

Thanks for considering this question!

Just spot checking, that looks like an extra dot/context.

I’m not sure about those withs, but I’d try:

{{ range sort .Params.historicalDate }}

Thanks @maiki, i think i may have tried that one before, and just ran it agian, and here’s the error it throws:

executing "partials/about/history.html" at <.Params.historicaldate>: can't evaluate field Params in type resource.Resources

Still digging…

You need to define a variable for your custom date parameter while piping it with the time function.

Then you will be able to sort the content in descending or ascending order as is the usual way with default dates in Hugo

Thanks for your direction here, @onedrawingperday. At what depth do you suggest defining the custom-date variable. Without making any changes to my code, inside the the range, i’m able to call it without any trouble, like this:

{{ with .GetPage "/about/history/index.md" }}
  {{ with .Resources.ByType "page" }}
    {{ range sort . ".Params.historicalDate" }}
      {{ dateFormat "January 2, 2006" .Params.historicalDate }}
    {{ end }}
  {{ end }}
{{ end }}

This outputs properly formatted time (e.g. “July 1, 2010”).

Outside the range, i don’t seem to have any access to it my historicalDate parameter.

@stephenpiscura I played a bit with the setup you described in your first post.

It seems that what I posted above is unrelated to the issue you experience.

But something does seem to be off with the way you have organized your Page Bundles, because the code you posted above does not seem right as @maiki indicated.

However currently there are no console errors because it seems that you are trying to fetch a headless bundle from within another headless bundle (?) which is not the way things work and Hugo ignores everything.

In any case I cannot know what’s going on without having a look at your project.

Also I have a question: how is that list supposed to look like? Newer items first or the other way?

Thanks for taking some time with this question, @onedrawingperday, i genuinely appreciate it. Here’s a look at the way my content is organized in this project:

content/
├── about
│   ├── _index.md
│   │   ├── history
│   │   │   ├── index.md (headless)
│   │   │   ├── historical-item-1.md
│   │   │   ├── historical-item-2.md
│   │   │   ├── historical-item-3.md

The content in question is displaying in the about/_index.html page, so i don’t think it’s the case that i’m calling a headless bundle from within a headless bundle. Rather, i’m calling a headless bundle from a section page (about/_index.html).

The timeline itself is meant to display oldest-to-newest items. It’s displaying nicely at present, just not sorted by the custom date parameter.

Try with all lowercase .Params.historicaldate

3 Likes

My goodness, this does the trick!

For the sake of completeness, here’s how the working code looks:

{{ with .GetPage "/about/history/index.md" }}
  {{ with .Resources.ByType "page" }}
    {{ range sort . ".Params.historicaldate" }}
      {{ dateFormat "January 2, 2006" .Params.historicaldate }}
    {{ end }}
  {{ end }}
{{ end }}

So i guess i’ll be going through this project and removing every instance of camelCase parameters.

Looking into this after reading your reply, it looks like there’s already an issue for this:

In any case, thank you @pointyfar for solving this for me!

1 Like

@stephenpiscura as I replied to you in the other bumped thread this is not what it seems.

@pointyfar was half right to indicate that you enter the parameter in lowercase but apparently you don’t need to do this everywhere.

The following does the sorting you need:

{{ with .GetPage "/about/history/index.md" }}
  {{ with .Resources.ByType "page" }}
    {{ range sort . ".Params.historicaldate" }}
      {{ dateFormat "January 2, 2006" .Params.historicalDate }}
    {{ end }}
  {{ end }}
{{ end }}
</body>

In a test repo I made locally using the sort function with the historicaldate parameter in lowercase creates the sorted list. But the parameter can be in camel case in the various pages resources i.e. historicalDate: 2012-06-27T13:32:36-04:00 and in other places of the template.

Note that I haven’t encountered this behavior myself before and above I was basically guessing about what might be wrong.

However I am tagging here @bep the maintainer of Hugo, because he is the one who knows whether the sort function by parameter requires that parameter entered in lowercase or whether this is a bug. Hopefully he can chime in here whenever he has the time.

It does. And you may call it a bug and create an issue and I’ll fix it. A little history lesson may shed some light:

  • Originally we preserved the case for config keys (including the keys in params)
  • Then at some point Viper, the config library we use, decided to normalize all keys to lower case. There were good reasons to do do this and I supported it.
  • This broke a lot of existing Hugo sites, however, because .Site.Params.historicalDate stopped working.
  • So I made .Site.Params.historicalDate and .Param "historicalDate" etc. case insensitive, but as you have found, there is no end to this …
2 Likes
1 Like