[Solved] How does a partial find out the top-level document that's being rendered?

(Hugo v0.19, Mac)

index.html has:

{{ $paginator := .Paginate (where .Data.Pages "Type" "==" "post") }}
{{ range .Paginator.Pages }}
  {{ partial "article-summary.html" . }}
{{end}}

From inside article-summary.html, I need to know whether I’m being rendered as part of index.html, or some other page. Nothing I’ve tried has worked. I can’t use $.Kind, or set a variable in index.html, or use $.Scratch, or even $.URL (which works inside the range, but not once you’re in the partial).

I’m actually going several levels deep with partials to keep the styling consistent across multiple top-level templates (article-summary.html calls blogpost-header.html, which in turn calls commentlink.html), but the problem starts the moment I leave index.html.

It looks like my only option is to duplicate the entire chain of partials, so that index.html calls one set, and other list pages continue to call article-summary.html. Unless there’s something I’ve missed in the documentation (easy enough to do…).

-j

Have you tried creating a variable before the loop starts, with the information about the current page?

For instance, if you want to generate article-summary.html on all pages except the home page, you can use something like:

{{ $homePage := .IsHome }}
{{ $paginator := .Paginate (where .Data.Pages "Type" "==" "post") }}
{{ range .Paginator.Pages }}
    {{ if not $homePage }}
        <!-- We're not on the homepage; render partial -->
        {{ partial "article-summary.html" . }}
    {{ end }}
{{ end }}

See the list of variables if you need other ways to determine the current page (like .RelPermalink if you also want to target a specific page).

Yes, and when I try to query it from inside the partial, it’s not set.

-j

If you say what I think you say, then variables defined in a template file (index.html) cannot be accessed in a partial (article-summary.html). Perhaps this is possible with scratch variables, but it probably will be easier to use a page variable like .RelPermalink or .Permalink like I mentioned in my previous post.

I’d already tried Scratch and .Permalink, and they didn’t work. As far as I can tell, nothing from index.html is visible once you’re inside a partial. Currently, it looks like I’d have to change all the partials into shortcodes, and then use .Parent. I haven’t tested that yet to see if there’s a significant performance penalty.

I’ve actually abandoned the idea for now, and solved my specific problem in a completely different way.

-j

The best way to pass variables from a template to a partial is to use the dict func.

I had vaguely noticed the example in the docs, but reading it now, it sounds like you’d then wrap the parts of the partial that don’t use the passed variable in a {{with .content}} block to get the normal behavior, correct?

{{ range .Paginator.Pages }}
  {{ partial "article-summary.html" (dict "content" . "realurl" $.URL) }}
{{end}}

article-summary.html:

{{if ne .realurl "/"}}
  {{with .content}}
    .Summary
  {{end}}
{{end}}

-j

1 Like

Yes, that is correct.