Block in a partial and defining in a page

Hi,

I’ve put a block in a partial1.html

{{ block "partial1content" }}Default partial content{{ end }}

Then I’ve tried to define the content in a template.

{{ define "partial1content" }}Some other sidebar content{{ end }}
{{ partial "partial1.html" . }}

However it never seems to make it into the partial?

If I plonk the partial template contents into the main template, then it all works as expected.

I am guessing that the scope of the block is restricted to the partial, whereas being in the template it works as expected.

Is there any way to make this work?

What I was trying to achieve is putting a .TableOfContents into a sidebar. I actually want the sidebar to have different content depending on where I am in the site.

(btw if I put .TableOfContents into the partial it doesn’t work)

Thanks!

1 Like

Blocks are reserved for the baseof.html templates only.

1 Like

I just filed https://github.com/gohugoio/hugo/issues/3929, which I believe would address this.

I also need to define blocks inside partials for better code organization.

Is there any alternative way?

3 Likes

Are they any alternatives? @johnson did you find something?

FWIW, I assumed that I could cut up my baseof.html template into constituent files to organise them in a more granular way… Perhaps more granularly than many users tend to do. Here’s the structrure of my layouts/ folder:

layouts/
β”œβ”€β”€ _default/
β”‚   β”œβ”€β”€ baseof.html
β”‚   β”œβ”€β”€ list.html
β”‚   └── single.html
β”œβ”€β”€ partials/
β”‚   β”œβ”€β”€ _global/
β”‚   β”‚   β”œβ”€β”€ 0-head/
β”‚   β”‚   β”‚   └── primary_head.html
β”‚   β”‚   β”œβ”€β”€ 1-body/
β”‚   β”‚   β”‚   └── primary_body.html
β”‚   β”‚   β”œβ”€β”€ 2-header/
β”‚   β”‚   β”‚   └── primary_header.html
β”‚   β”‚   β”œβ”€β”€ 3-main/
β”‚   β”‚   β”‚   └── primary_main.html
β”‚   β”‚   └── 4-footer/
β”‚   β”‚       └── primary_footer.html
β”‚   └── menus/
β”‚       β”œβ”€β”€ basic/
β”‚       β”‚   β”œβ”€β”€ recursion-full.html
β”‚       β”‚   β”œβ”€β”€ recursion-none.html
β”‚       β”‚   └── sectional.html
β”‚       β”œβ”€β”€ iconographic/
β”‚       β”‚   └── social-media.html
β”‚       └── special-purpose/
β”‚           └── a11y-jump-navigation.html
β”œβ”€β”€ shortcodes/
└── 404.html

Several of the partials, in turn, reference partials that are β€œmore deeply nested”.

To explain, here is the code in two of the files above:

layouts/_default/baseof.html

<!DOCTYPE html>
<html lang="en" class="w-full h-full">
{{- partial "_global/0-head/primary_head" . }}
{{- partial "_global/1-body/primary_body" . -}}
{{- partial "debug/json.html" (dict "siteParams" .Site.Params "currentContext" site.Menus) -}}
</html>

layouts/partials/_global/1-body/primary_body.html

<body class="w-full h-full">
<div class="w-full flex flex-col md:flex-row md:flex-wrap min-h-screen">
  {{- partial "menus/special-purpose/a11y-jump-navigation" . }}

  {{- partial "_global/2-header/primary_header" . }}
  {{- partial "_global/3-main/primary_main" . }}
  {{- partial "_global/4-footer/primary_footer" . }}
</div>
</body>

layouts/partials/_global/3-main/primary_main.html

{{- block "body-global-main" . }}
<main id="main" role="main" class="body-global-main">
  {{ .Content }}
</main>
{{ end -}}

What I’d been hoping to do was then define {{block "..."}} blocks in the various partials and then β€œredefine” ({{define "..."}}) them in page templates of greater specificity, only overriding/redefining blocks that were in need of β€œSection” specific changes.

I found this Discourse thread because, after having setup my code as displayed above, I began working on overriding the body-global-main block (initialised in primary_main.html as illustrated above) in layouts/_default/home.html… and it wasn’t working.

I can see now from @bep 's comment in this thread that the constructs {{block}} and {{define}} are β€œonly meant to be used in baseof.html templates”. For anyone who was thinking of doing something like what I was trying, here’s the page to look up β€œbaseof” (and other such) templates: Template lookup order .

It really would be great if we could cut up our baseof.html templates so that they are easier to parse through but, lacking that capability, for others who come across this thread, the way to go as of today is to:

  1. Keep ALL markup that you want to override using {{block}}/{{define}} constructs in a single file…
  2. Then, simply accept that we’ll be duplicating the baseof.html at least a few (e.g., copy/paste in home.html which is what I need to do in my case) and then override in higher-specificity List/Single pages as needed.

The above doesn’t preclude a mix of cut-up of code like <head> and opening/closing <body> </body> tags into partial files. This should at least help keep things a bit cleaner. E.g. - snippets of what I’m doing now:

layouts/_default/baseof.html

<!DOCTYPE html>
<html lang="en" class="w-full h-full">
{{- partial "_global/0-head/baseof_head" . }}

layouts/_default/baseof.html

<!DOCTYPE html>
<html lang="en" class="w-full h-full">
{{- partial "_global/0-head/home_head" . }}

The above illustrates that I’ve moved removed the use of block ({{block "head-styles-global" . }}) in those two partials and thus, I’m able to better control and override which JS and CSS files are used globally (in {{partial "_global/0-head/baseof_head" . }}) by overriding the partial that is loaded in layouts/_default/home.html to be {{- partial "_global/0-head/home_head" . }} instead. To explain, the site’s home page will have vastly different styling and JS requirements and so, they shouldn’t be loaded with every page.

I do hope that maybe we can simply override {{block}} with {{define}} across β€œsecondary” baseof templates in the future. I sorta wonder if maybe Hugo could provide this capability by defining hierarchical relationships between types of Template files like so:

  1. ROOT (any block defined here can be overridden in children): baseof.html (and variations thereof)
  2. Second-Tier: home, list, single, section, page ({{define}} blocks in these could then override {{block}} definitions in baseof.html. Templates of this tier can also define new blocks of their own.
  3. Third-Tier: content/TREE-STRUCTURE based specificity templates. E.g. content/pages and content/posts would both imply that they may have customised layouts in layouts/pages/[list|single].html and layouts/posts/[list|single].html. Third-Tier templates wouldn’t be able to define new {{block}} blocks, they’d only be able to override blocks defined in β€œlower level” tier templates.

I hope this info helps others in the future!

Related threads:

  1. Blocks and define override in hugo theme
  2. Support Base Templates and Blocks in partial rendering