Hugo

Templates: multiple parameters?

Hello Hugo community,

It looks like Hugo doesn’t currently support passing more than one parameter to templates. Is this true? You see, I’ve been using the following template for a navigation bar:

<ul>
  {{ range . }}
    <li>
      <a href="{{ .Url }}">{{ .Name }}</a>
      {{ if .HasChildren }}
        {{ partial "nav" .Children }}
      {{ end }}
    </li>
  {{ end }}
</ul>

I pass .Site.Menus.main into this partial from the main template.

But when I try to add support for checking “is this the current page”, I need access to .IsMenuCurrent, which is part of the page rather than the *hugolib.MenuEntry. So, what I’d like to do is pass in both the current menu and the top-level page object:

{{ partial "nav" .Site.Menus.main . }}

Unlike shortcodes, however, there doesn’t seem to be a mechanism to use multiple parameters (and, as far as I can tell, I can’t call a shortcake from inside a template).

So… how would you solve this problem? Could support for multiple parameters be added to templates? Is there a better way of doing this?

Thanks!

Jon

You can save the outer context in a variable:

{{ $outer := . }}

And then:

 {{ if $outer.IsMenuCurrent ... }}

In your case you also would have to reorg. your partials a bit to get the correct context into the partial.

Also, even if you are in an inner context, e.g. inside a range or with, you may always access .Site.Menus.main by adding $ before it, i.e.:

$.Site.Menus.main

So you do not need to pass it into a partial.

I forgot where I learned this trick, but it enabled me to make my earlier change to the the internal rss.xml template less redundant in the following patch:

3 Likes

Dang, I didn’t know that …

Don’t worry, I learned it only 36 hours ago, and I can’t even remember where I got that information. Let me go search… (Searched for like 5 minutes…) Ah! There it is!

The posted answer suggesting the use of {{$.Name}} points to the Go text/template documentation under Variables:

When execution begins, $ is set to the data argument passed to Execute, that is, to the starting value of dot.

but, without an example, and without an explanation on how it is used, it is totally not obvious to me and I would have totally missed it or just plain don’t get it. :-p

Note to self: Add it to the Hugo docs. :slight_smile:

But back to the original question about passing additional parameters to {{ partial }}

Here is an example.

Say I have this code in a partial for the taxonomy “tag”

   {{ $baseurl := .Site.BaseUrl }}
    <ul id="tags">
      {{ range .Params.tags }}
        <li> <a href="{{ $baseurl }}/tags/{{ . | urlize }}">{{ . }}</a> </li>
      {{ end }}
    </ul>

(BTW if I understand @anthonyfok above one doesn’t need the $baseurl anymore just $.Site.BaseUrl) :-).

SO

instead of making a separate partial file for every taxonomy I want to pass the taxonomy name in the partial call

{{ partial "page-taxonomy.html" "tags" }}

to something like this

{{ $baseurl := .Site.BaseUrl }}
   <ul id={{ .Get 1 }}>
    {{ range .Params.{{ .Get 1 }} }}
    <li> <a href="{{ $baseurl }}/{{ .Get 1 }}/{{ . | urlize }}">{{ . }}</a> </li>
    {{ end }}
   </ul>

Possible? If so is this the correct syntax?

The issue with this is that it only lets me reference the thing that was passed into the template (in my case, a *hugolib.Menu). This doesn’t help me get back to the Page object, just back to the Menu that I’m currently iterating over.

I will investigate the Scratch mechanism to see if it can help me…

Ok, it doesn’t look like Scratch will help me: only Node objects have a Scratch, so there’s no way to correctly handle recursive navigation partials: I’d have to overwrite a shared Scratch while rendering /foo in order to render /foo/a, which would preclude me from then correctly rendering /foo/b.

So, it looks like I really, really need to be able to pass multiple arguments to a partial template if this is even going to work correctly.

To be correct, both Node and Page have Scratch.

That said, it would be fairly cheap and easy to add it to the Pager (or whatever that struct is called).

I ran into this problem just now. I had two partials that need .Site.BaseURL, but only have access to a custom Params object (one from .Site.Params.Header and other from .Site.Params.Cells.List). Refactoring to make this accessible is a bit frustrating, but I guess it’s the only option for now. I’d love to have arguments in the same manner as shortcodes.

See

https://github.com/spf13/hugo/pull/1463

And thanks to @notzippy this is now merged into Hugo 0.15-DEV:

https://github.com/spf13/hugo/commit/3a27cefec1beb8e2e49ec206264d7d19cde0ffae

This will fix many headaches. @spf13 - time for a 0.15 release?

I think the absUrl function should handle rewriting the url with the .Site.BaseURL , but yes it was one of my original motivations for adding the dict function.

Doesn’t it? That is the main point of it, if I remember correctly.

This is a today’s answer to the old question. I am posting to help those who do search.

You can use dict function. It is documented here: