HUGO

How do I override Base Template Blocks from a Theme Component?

I have a simple theme with a baseof.html containing several blocks (header, main, footer etc). How can I make use of / define these blocks in the left-most Theme Component and make the changes apply not only to single/section/list.html – but to every page?

If I add a baseof.html in the left-most Theme Component, it is merged on a file level and replaces the original baseof.html. This is expected behaviour according to the documentation, but I would like to be able to override the original baseof.html on a block level.

My goal is to have a base/template theme that I can built on top of with Theme Components, but not being able to define blocks in the baseof.html is a real bummer.

Have anyone found a solution to this problem, short of ditching blocks entirely and use partials instead?

In my head you have 3 building blocks to build with:

  1. You can add your block “implementations” in the list.html etc. in your theme.
  2. You can call out to partials in the {{ block . }}{{ partial "foo" . }}{{ end }} which would allow a combination of the above and components being able to override via a partial.
  3. Drop the blocks and use partials.

And some combinations of the above.

I seems like the second option is the only way to go for my use case, but it would have been nice to work primarily with blocks, as it is such a clean and transparent solution. With partials I have to write checks to see if the partial exists or not, which is much more clunky and makes the baseof.html less readable for others. It is so nice to have most of the basic code visible in the baseof-file and not spread out over many partials!

Is there nothing “below” baseof.html in the Lookup Order that at the same time affects all rendered pages?

Thanks for your suggestions!

I can add that the recent introduction of “inline partials” is more useful than it sounds when you start using it. The big plus with partials vs regular templates is that you can assign the result to variables, which allows constructs ala:

{{ $inner := partial "foo" . }}
{{ partial "decorate" $inner }}
2 Likes

Inline partials looks interesting, thanks!

I will try to explain how I plan on using (inner) partials in my base Theme Component to achieve a transparent and easy to read baseof.html which can be overridden and expandend by a child Theme Component.

The main problem with using block’s in a base Theme Component is that you can’t define / override them for the entire site in a child Theme Component. Consider the following example: We add an empty {{ block "aboveHeader" . }}{{ end }} in the base Theme Component in an attempt to make room for additional code to be injected by the child Theme Component, if needed. It should be possible to define this block both to certain parts of the site, as well as globally – but it’s not.

The problem is that you can’t define block’s in the child Theme Component for the entire site; the baseof.html is not an option, as it will replace the base Theme Components baseof.html in its entirety. There is also no way (that I know of) to use files that is not in the Lookup Order to define blocks.

As I just learned by looking further into inline partials (thanks @bep), you can define partials much like you define a block, with the added benefit of being able write code to a file that will be injected into the baseof. Example-time:

<!-- This is how blocks are normally used in baseof.html -->
{{ block "something" . }}{{ .Title }}{{ end }}
<!-- This is how inline partials can be used in baseof.html -->
{{ define "partials/something" }}{{ .Title }}{{ end }}
{{ partial "something" . }}

This method is slightly more verbose, but allows us to use partials in the same way as blocks:

<!-- layouts/partials/something.html -->
{{ define "partials/something }}{{ .Site.Title }}{{ end }}

Instead of defining a block, we define a partial that can either be present inline in baseof.html or in a file located in the partials folder.

Hope this information can help someone else trying to build Theme Components that can be used as templates and extended through other Theme Components!

I’m experimenting with ways to make empty partial references shorter as the following is unnecessary long-winded:
{{ define "partials/something" }}{{ end }}{{ partial "something" . }}

I tried to use {{ with partial "something" }}{{ . }}{{ end }}, but Hugo is complaining about not finding the partial. Which is strange. I expected it to silently ignore this code if the partial does not exist.

Any advise is welcome!

Maybe, but that is how it is. Slightly misspelling the partial names is a very common source of error. I vaguely remember adding a HasTemplate or something, but I cannot find it in the documentation … Maybe someone remembers …

Slightly misspelling the partial names is a very common source of error.

In this case the name of the partial should not matter as it does not exist. Maybe with works best with variables and not so much for checking the existence of partials?

I vaguely remember adding a HasTemplate or something

May it is templates.Exists your thinking of? I fooled around a bit with this function, but never got anything that would be shorter and leaner than the original line of code.

{{ with "something" }}
{{ if templates.Exists . }} 
{{ partial . "args" }}
{ end }}
{{ end }}

Verbose, I agree.

Hm, maybe I’ll end up using the original line of code after all, it’s not that long :slight_smile:

But please do raise an issue on GitHub to make partials not raise an error when template not found. I see the issue, and it would probably be more useful to return an empty string…

1 Like

Bep, I just used inline partials for a refactoring, and you’re right it is really cool because I can use it as a function in my template and avoid the necessity to create a myriad of template files.

But I do not see anything else regarding the use of inline versus of a regular template.
Any other use case I can steal the idea from :slight_smile: ?

No, that difference is just the file vs not a file, but that is a big difference in practise… For certain things I seem to create smaller partials for stuff I would not bother do that with (because I had to create a file).

1 Like

Ah ok cool.
Exact, first time I ever made “functions”. Pretty neat.

Ahhhh Hugo is such an exiting beast !!! Reminds me the old time with zope.org when a spare time amateur like me could do really cool stuff.

Thank you for making an issue on GitHub. I am considering making another one which clarifies that I do not want to change the current behavior of partial, but rather make {{ with partial }}... not throw an error when the partial does not exist.

Making regular partial fail silently would of course make the code snippet even shorter, but might cause confusion when something is misspelled. I think this is why the vote in the issue you created was against the proposal.

1 Like