What's the "Hugo way" to output this common pattern?

Here’s something I’ve spent some considerable time trying to figure out. It seems it should be very easy to do, perhaps someone could point me in the right direction?

Let’s suppose I have a site about food, and on the homepage I want to show a selection of featured recipes from the section .Recipes. In the front matter of each recipe page, there is a key “meat:” which can have values such as “beef”, “chicken”, “veggie” etc.

On the homepage I want to display separate lists of recipes for different meats.

So far I can:
Get all the pages in “Recipes” section:
{{ $recipes := where $.Site.RegularPages “Section” “recipes”}}
{{ range $recipes }}…

At this point I am stuck. When I try to query .Params “meat” and do different things for “beef”, “chicken” “veggie” etc. I get stuck inside the .Params.meat context and lose access to the .Page variables I need.

I am using a workaround, changing the front matter to something like
meatIsBeef: true
meatIsChicken: true
etc
and then
if .Params meatIsBeef → do something
if .Params meatIsChicken → do something else

But I feel like there must be a better way. Thoughts?

Could we see the code please, this works:

<h1>{{.Title}}</h1> {{/* list page title */}}
{{ $recipes := where $.Site.RegularPages "Section" "recipes"}}
{{ range $recipes }}
<h2>{{.Title}}</h2> {{/* individual recipe page title */}}
  {{ if .Params.meat}}
    {{ .Title }} contains {{ .Params.meat }} {{/* individual recipe page title still works in the if statement */}}
    {{.Content}}
  {{ end }}
{{ end }}

Thanks, indeed that’s the kind of workaround I’m using.
What I’m asking is if it’s possible to do something like:

{{ $recipes := where $.Site.RegularPages "Section" "recipes"}}
{{ range $recipes }}
{{ if .Params.meat.chicken}}
/* code to show recipes containing chicken */
{{ if .Params.meat.beef }}
/* different code showing recipes containing beef */

Unfortunately I don’t have the exact code I was trying as it felt like a lost cause and I’ve moved on for now. I understood it’s impossible to access the page variables inside the range because the “dot” is “meat” — error msg: <.Params.meat.beef>: can’t evaluate field beef in type string

It’s just a bit hard to believe there isn’t a way to achieve the above pattern relatively easily, so just wanted to check my understanding here.

Save the page variable before your range in another variable and refer to it in your conditionals

So in the frontmatter do you have:
meat: beef

If so this makes no sense:

beef is found from .Params.meat
there is no .Params.meat.beef

Hence the error:

Yes, indeed! I can’t find a way to get to .Params.meat for each page and read whether it’s beef or chicken.

<h1>{{.Title}}</h1> {{/* list page title */}}
{{ $recipes := where $.Site.RegularPages "Section" "recipes"}}
{{ range $recipes }}
<h2>{{.Title}}</h2> {{/* individual recipe page title */}}
  {{ if eq .Params.meat "beef"}}
  <p>found beef</p>
    {{ .Title }} contains {{ .Params.meat }} {{/* individual recipe page title still works in the if statement */}}
    {{.Content}}
  {{ else if eq .Params.meat "chicken" }}
    <p>found chicken</p>
  {{ else }}
    <p>no meat here</p>
  {{ end }}
{{ end }}

It works, thank you so much. Bit embarrassing, but glad it was easy!

One other way to look at this would possibly be:

{{ $recipesSection := site.GetPage "recipes" }}
{{ $allRecipes := $recipesSection.RegularPagesRecursive }}
{{ $cheapToMake := where $allRecipes "Params.price" "<" 100 }}
{{ $withChicken := where $allRecipes "Params.meat" "chicken" }}
{{ $withBeef := where $allRecipes "Params.meat" "beef" }}
{{ $withChickenOrBeef := $withChicken | union $withBeef }}
{{ $cheapWithChicken := $cheapToMake | intersect $withChicken }}

Etc. (I typed in the above, so I may have done a mistake or two, but logically it should be correct).

4 Likes

Thank you, I will bookmark this for further study!

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