What is different between .Render and partial?

I think both of them are functions that copy code from other files to the working file. So what is the difference? And when should I use .Render (or partial)?

Two previous threads:

Ops, sorry, I didn’t see it early. My bad.

I had the same question and asked @regis about that. Here’s his great answer and explanation:

.Render vs partial

.Render is a method of the page object. Its greatest advantage is template lookup order. It will use Hugo’s template lookup order to define which template file to use. So if you have two different title.html template files, one for your entries of type post and one for your entries of type page each living in a directory named after those two types:

  • layouts/_default/title.html
  • layouts/post/title.html
  • layouts/page/title.html

Hugo would grab the type of the page .Render is used on and find the right file for you. And if the file does not exist, gracefully fallback to your default file.

.Render does not take any argument. The context passed to the template file is always the context of the page the method is used on.

partial on the other hand is a global function. It can be used anywhere. It takes two arguments, the file path and the context to be passed to the template file.
It does not have any template lookout logic. So back to our title.html example. You would have to place your two files in the layouts/partials directory

  • layouts/partials/post/title.html
  • layouts/partials/page/title.html

And you would have to grab the page type and use it to build the partial’s path yourself prior to passing it to the partial function and make sure the file exist or fall back to a default one. (Luckily there is templates.Exists now).

So which one to use?

Now by those two definitions, it appears both have their pros and cons, but the limited context passed to the template file by .Render will often be a problem for me. Unlike partial there is no way to conveniently complement or replace this default context.

For exemple, from within your partial you often need to know beyond the page context, like is this template file being used on a single page or a list page?

Let’s say you have a template file called article.html to display your title, featured image and text.
The only difference in the file is calling .Summary when in a list template vs .Content when in a single template. A simple ternary condition could do!

Using .Render though you would have no way to know if you’re supposed to call for .Summary or .Content , you’ve got nothing to test your condition on.
So in order to benefit form its amazing template lookup feature, you would have to create two quasi-identifcal html files, article_list.html and article_single.html (in each of your type directories) and replace the part dealing with .Summary or .Content .
This doesn’t seem much for many but it’s a no go for me. Having several identical template files and maintaining multiple files when changing the HTML of this section is a no go for me. (principles… :disappointed:).

For these reasons, on my website which matches this use case, I had to fell back to using partial . This way I’m able pass this information (list or single) to the context, and test my condition on it)

Oh and an issue…

Also, while using Custom Output format, I found that .Render only look for files matching the main Output Format rather than the current one (#5090).
So here again, when dealing with Output Formats, I had to fall back to partial and do the template lookup and file exist check myself.

4 Likes

This will, among other similar known limitations, be fixed in Hugo 0.55.

3 Likes

.Render is (now) documented to offer greatest advantage in list template, where you might be most likely to loop through potentially different types of pages. I’d offer another scenario, where you want to show page snippets in search results (which also loop through a bunch of potentially different types of pages). So it’s no longer positioned as a general purpose alternative to partial.

But you could mimic any collection of view templates with a single partial with an N-way test on page type, section or kind.

The one place where .Render has a clear advantage is in modularity. Suppose you’re writing a theme and you expect others to write plugins for new page types. If your theme had a partial with the N-way test, you’d have to add a case to handle the plugin. But if you use .Render, plugin writer simply writes an additional view template of the right name and it all just works.

So I think it’s an elegant solution to a relatively rare problem, FWIW.

1 Like