.Render: How to identify top level page/template from li.html

I love the .Render approach and think people should use Content View templates more.
I’d love to use the same li.html from list.html and single.html

I suspect the main reason people don’t use it this much is the impossibility from the Content View template (li.html or else) to do this:

{{ if eq topLevelPage.Kind "page" }}
	{{ .Content }}
{{ else }}
	{{ .Summary }}
{{ end }}

For most implementation (posts etc…), this will be the only difference between your list and single pages.

I’ve been looking for a workaround for this since I started with Hugo hoping experience would eventually pay out, it has not as of today :frowning:

Has anyone found one ?

Would it make sense to make $ available from “rendered” content view templates ?

I’m not sure what your problem is here … But you are the dot expert here …

A Content View rendered via .Render will get the correct … dot, so this should work:

{{ if .IsPage }}
	{{ .Content }}
{{ else }}
	{{ .Summary }}
{{ end }}

OK; I see what you are talking about now … What you want isn’t possible. And I don’t know how to (in a simple way) support in the code, either.

What we could consider (but we should think hard before doing it), is to add some kind of wrapPage template func. So you could do

{{ range .Pages }}

{{ $wrapped := wrapPage . $ }}
{{ $wrapped.Render "li" }}

{{ end }}

And then in your li.html:

{{ if .Outer.IsPage }}
	{{ .Content }}
{{ else }}
	{{ .Summary }}
{{ end }}

The names above are just taken out of thin air, but you should get the drift.

If you call .Render from different templates and you want to have a different rendering, then it’s logical to create several .Render and call one that is needed in a particular template.

If your renders has a common part, you can put it in the partials.

In most cases they are exactly the same but for .Summary and .Content (and possibly some minor tweaks)

Nobody wants to have to maintain two different Content View template with the same html. It means updating your html in two places when making changes.

So you end up doing this:

{{ range .Pages }}
    {{ partial "project/li" (dict  "Parent" $ "Page" .) }}
{{ end }}

Which does not benefit from the template lookout of .Render and needs a context passed as dict. It is fine, I don’t mind this implementation, but it seems everyone uses partials for templating while this should only be a secondary templating feature.

I just wish we could encourage people to use .Render. I strongly believe it is not adopted at all for the reason I am putting forward (but will peruse on the theme showcase to make sure).

Now that I see this, I understand there is no simple way to do this.
The ideal scenario would be that $ is available from within the rendered content view.

As I understand it, from within a range or with you always get the top level context as $ and the current context as .
Couldn’t .Render systematically pass along to its rendered output those two contexts as is ?

(I guess not, but I’d hate myself for not asking ;))

It is available, but it isn’t the dollar you want. Even if I wanted to dig into Go’s template package, what you suggest isn’t possible on the Einstein level. There is no way to guess what the “$” should be.

I see.

The other suggestion might be to be able to pass a context as argument, at least we coud benefit from the template lookout logic. But this is far from ideal, it being the reason I dislike partials :slight_smile:

By the way, I’ve browsed a few themes, Academic doesn’t use it, Casper (1 and 2) neither. I’m not sure what are the best exemple to look at, but those seemed popular.
The few .Render implementations I have seen involves @Mikhail suggestions: copy/paste with only one or two different lines :frowning:

I can understand in this context (pun unintended), that not too many people are willing to use .Render.

I use 4 renderers in my project and I think it’s very convenient. I’m perfectly free to choose a render when I call it from a template.


Sure but in your case their html seems to be very different.
In many cases, their html will be very simliar and maintaining them means making changes 4 times.

There is already a context passed as an argument. We cannot change the “.” – that would be pretty glass house breaking. So it needs to be something else: And to avoid breaking stuff you would have to decorate the “.” with another … But I’m not sure this is important enough.

I’m not sure either, I just wish Content Views adoption could be broaden, I really like them.

We’ll just have to keep using partial and mock the template lookout by dynamically building the partial path with .Type.
It feels a bit too hacky for my liking, but that’s just me.

For the rare case where Content Views are exactly the same or completely different, I’ll use .Render!

So turns out there was an obvious solution: .Scratch…
I use this in my single.html

{{ define "main" }}
	{{ .Scratch.Set "content" true }}
	{{ .Render "li" }}
{{ end }}

And then from within my li.html

<div class="bm-Entry__content bm-grid__main user-edit">
    {{ if .Scratch.Get "content" }}
        {{ .Content }}
    {{ else }}
        {{ .Summary }}
    {{ end }}

Damn, took me some days…
I guess I coud even store my top level page context in there and get what I need from it…

I don’t see how scratch can help you here. There is a fair amount of concurrency going on here.

You are right it worked on “hugo serve” but no on real deploy…
My idea was to use .Scratch to attach an information to the page I was about to .Render
I guess once you .Scratch something on a page, it keeps it during the whole build…

There is a fair amount of concurrency going on here.

What do you mean by concurrency?

It means that the list page and the single page using this content view may be rendered at the same time. So the “content” flag may be true for the list template.

So the “content” flag may be true for the list template.

I see what you mean now…

Felt too good to be true :wink: