Hugo

{{ template }} vs. {{ partial }}

I guess this is a question for @bep

I’ve been using {{ define "template" }} within some of my partials (usually to handle iterating over a list of mixed content blocks each of which has a different template … I find this cleaner than lots of {{ if }} {{else}} statements intermixed with HTML.

I noticed today that those template definitions are not scoped to that particular partial’s file and can be used from other partials (acting, from what I can tell, identically to a partial). I was wondering if there is a distinction (other than syntax) and what you see as the possible use-cases for {{ templates }} vs. {{ partials }}.

I don’t think I can answer your question, but I wanted to clarify for myself: when you say {{ templates }}, do you refer to baseof blocks?

No,
but like baseof, template is a Go Template “Argument” (see https://golang.org/pkg/text/template/) rather than a Hugo-specific thing (like partial).

From Go Docs:

{{template "name"}}
	The template with the specified name is executed with nil data.

{{template "name" pipeline}}
	The template with the specified name is executed with dot set
	to the value of the pipeline.

{{block "name" pipeline}} T1 {{end}}
	A block is shorthand for defining a template
		{{define "name"}} T1 {{end}}
	and then executing it in place
		{{template "name" pipeline}}
	The typical use is to define a set of root templates that are
	then customized by redefining the block templates within.```

it works like this:

// in a layout
<div>
    {{ template "myTemplate" . }} // note optional context "pipeline" ... the dot
</div>

{{ define "myTemplate }}
    <p>Hi</p>
    <p>The context is: {{ . }}</p>
{{ end }}

Hugo is using those “internal templates” at some point, but there hasn’t been much talk of them in the context of development.


One thing that I have noticed:

You can send content “programmatically” to different partials using print/printf (see this use case by Forestry : https://forestry.io/blog/3-tips-for-mastering-blocks/). It doesn’t seem to work with template (at lease not in the ways that I have tried).

so…

// Assuming that you have files: 
// `partials/blocks/a.html`,  
// `partials/blocks/b.html`, and 
// `partials/blocks/c.html`

{{ $blocks := ( slice "a" "b" "c" ) }}

{{ range .blocks }}
    {{ partial ( printf "blocks/%s.html" . ) }}  // works
{{ end }}

{{ range .blocks }}
    {{ template  . }}  // doesn't works
{{ end }}

{{ define "a" }}
  <div class="">A</div>
{{ end }}
{{ define "b" }}
  <div class="">A</div>
{{ end }}
{{ define "c" }}
  <div class="">A</div>
{{ end }}

1 Like

My 50 cents,

  • So, I like to think of templates defined by “define” as mostly local macros, esp. useful for doing recursion (e.g. navigation tree)
  • It’s important to understand that the namespace is global, so for local macros, make the name as unique as possible.
  • These templates needs to be defined at parse time, and if you want to create a “macro collection”, you could use the fact that the files are parsed in lexicographically order and name the template file to make sure it comes before the others (see example below)
  • partials is a Hugo thing, with a similar API, but with an option to cache the result and it also supports the return keyword. And it’s a partial per file in a well defined location that allows for theme overrides etc.

This opposed to partials which are defined during parsing? (i.e. hugo won’t parse them if they are not used?)

Both are … defined by parsing and both are parsed even if they’re not used, but you will not get complaints about missing partials until you try to run it.

1 Like