Page order isn't the default with GroupByPublishDate and page weights

In a partial used within list and term templates, I get the subpages for the page:

{{ $pages := where $page.Pages "Kind" "in" (slice "page" "term") }}
...
{{ with $pages }}

I filter for the “pinned” pages and display those first:

{{ $pinned := where . "Params.paige.pin" true }}

{{ range $pinned.ByPublishDate.Reverse }}
    {{ partial "paige/page.html" . }}
{{ end }}

Then I get the “unpinned” pages and display those, grouping by month and day:

{{ $unpinned := complement $pinned . }}
{{ $pagegroups := $unpinned.GroupByPublishDate "January 2006" }}
{{ $pager := $page.Paginate $pagegroups }}

{{ range $pager.PageGroups }}
    <h3 class="h5 paige-date-header text-center">{{ .Key }}</h3>

    {{ range .Pages }}
        {{ partial "paige/page.html" . }}
    {{ end }}
{{ end }}

I assumed the unpinned pages were ordered using the default order:

Weight > Date > LinkTitle > FilePath

If I have some unpinned pages with dates and no weights, they’re ordered correctly.

However, if I add weights to those pages, they’re still ordered by date, which contradicts the default order.

How can I get the default “Weight > Date > LinkTitle > FilePath” ordering within a page group made using the above approach?

With these methods…

GroupByDate
GroupByExpiryDate
GroupByLastmod
GroupByParamDate
GroupByPublishDate

The resulting groups are sorted by the grouping field. For example, if you group by expiration date, the pages within each group are sorted by expiration date. Although not explicitly documented, this is what I would expect, similar to SQL’s “GROUP BY” clause.

To sort the pages in each group (e.g., by weight):

{{ range .Pages.GroupByExpiryDate "2006-01" }}
  <p>{{ .Key }}</p>
  <ul>
    {{ range .Pages.ByWeight }}
      <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>
    {{ end }}
  </ul>
{{ end }}

The problem here is that we are inconsistent. GroupBy and GroupByParam retain the original sort order order (which may or may not be the default sort order) in each group, but the five date grouping functions do not.

To clarify, if you sort a page collection by Title in descending order, the pages in each group are still sorted by Title in descending order after using the GroupBy or GroupByParam methods.

{{ $p := sort site.RegularPages "Title" "desc" }}
{{ range $p.GroupByParam "myParam" }}
  <h2>{{ .Key }}</h2>
  {{ range .Pages }}
    <h3><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h3>
  {{ end }}
{{ end }}

Although a breaking change (albeit with limited exposure), I think we should change the Group By date methods to behave like GroupBy and GroupByParam.

https://github.com/gohugoio/hugo/issues/11564

Additionally, the GroupByParamDate function does not work with unquoted TOML YYYY-MM-DD formatted dates:

https://github.com/gohugoio/hugo/issues/11563

1 Like

So, I’m waffling on this. Sorting the pages of each group by the GroupBy date is, I think, the least surprising, and you can change the sorting within the groups as I’ve shown in my initial response.

I’m not sure there’s a right answer here, but leaving things as they are (a) won’t break existing sites, (b) is consistent with SQL behavior, and (c) is a little bit better from a performance standpoint (we don’t have to iterate twice over the page collection).

Thoughts?

I think the current behavior is fine, for the reasons you listed, if we add a .Pages.ByDefaultOrder so it’s clear how to restore the default order within a .GroupBy* result (with the documentation now explaining that the default order is .Pages.ByDefaultOrder).

@jmooring Now that I look, I don’t see a way to manually recreate the default order: GroupByWeight, GroupByTitle, and GroupByFilePath don’t exist.

Your example groups by expiry date, then orders by weight, but that isn’t the default order, because pages with equal weight won’t have a suborder for title or file path.

To get the default order, you’d need to get the list of unpinned pages, then group by year/month date, then for each date group, group by weight, then for each weight group, group by title, etc. How can I do that?

I am unable to reproduce, because…

I assumed it was ordering by weight, and then nothing else. Good to know it applies the default order within that. Thanks.

Yeah, so you can think of ByWeight as ByDefaultOrder.

1 Like

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