Accessing data from iterrated imported partials

I’ve been trying to figure out how to get partials to be imported dynamically based on array in my data yaml file. Partials themselves use data and I’m not able to get this working.

data/site.yaml file has content:

sections:
  - banner
  - carousel
  - features
  - cta
  - infobox

partials with same names exist in partials/sections/ as:

partials/sections/banner.htm
partials/sections/carousel.html
etc...

In one of the layout files, I’m trying to iterate and import these partials.

{{ range .Site.Data.site.sections }}
  {{ partial (printf "sections/%s.html" .) . }}
{{ end }}

But I come across error:

render: failed to render pages: render of “/home/user/Desktop/test.com/content/_index.md” failed: “/home/user/Desktop/test.com/themes/test/layouts/_default/home.html:4:5”: execute of template failed at <partial (printf “sections/%!s(MISSING).html” .) .>: error calling partial: “/home/user/Desktop/test.com/themes/test/layouts/partials/sections/banner.html:2:18”: execute of template failed at <.Site.Data.site.banner_title>: can’t evaluate field Site in type string

Any idea how I can do this properly?

Thanks

The Dot! Context.

Anyway. In very nested layouts you end up having . not “meaning” the context of “the current page”. In this very specific case you can instead of .Site use site and this will call the site. In other cases that might not be so easily to exchange.

Just remember that:

{{ . }} <-- this is the page context
{{ with .Something }}
  {{ . }} <-- this is the Something context now
{{ end }}
{{ . }} <-- this is the page context again

There is this very old but very well written introduction to the context. I am not 100% sure if it’s up-to-date with the current Hugo - it should. But that does not take away anything that is said/written in that article about the dot. Learn that and be aware of it.

I was able to accomplish what I need like so:

{{ $cont := . }}

{{ range .Site.Data.site.sections }}
  {{ partial (printf "sections/%s.html" .) $cont }}
{{ end }}

It works. Not sure if it’s the right way however.

I will use your suggestion instead. Feels like a better approach.

just two hints:

  1. I would not name the variable $cont.
    saving three letters but reading that later what does it stand for? Context, Continue, Content?

    These days there is not much gain in shortening variable names, so I would use something like $context, $page or $pageContext - use speaking variable names so you can read one line of code without needing to look up the initialization. (p.s. a quite common abbreviation for context would be $ctx)

  2. code defensive - you might want to do some error checking.

    What, if the data file is missing, the sections list is missing (or empty). Currently this is silently ignored.

    What about a spelling mistake in the list and/or the partial does not exist. You might want to give a nice warning or error message instead dumping a stack trace.

    use if, with and else to do some checks fe templates.Exists

    depends on how and where that is (re-) used

1 Like