How to use variable variable names in Hugo / Go templates

Here’s the scenario, I have a markdown file at content/api/tickets/tenants/incidents.md. I also have a data file at content/api/tickets/tenants/incidents.yaml. The markdown file needs to use the yaml to populate the content.

The template however doesn’t know any of this information before hand. So while I can get the data if I hardcode (for example) {{ (index .Site.Data.api.tickets.tenants.incidents $endpoint).requestBody.content | jsonify }} this won’t work.

What I need is something similar to a variable variable that works with maps:

{{ $wontwork := 'tickets.tenants.incidents' }}
{{ (index .Site.Data.api.$wontwork $endpoint).requestBody.content | jsonify }}

I figured I could set $wontwork in the markdown front matter so the theme would know where to look for the associated data file. Does this make sense and can someone point me in the right direction for how to accomplish this?

{{ $fileName := "mydatafile" }}
{{ $keyInDataFile := "mykey" }}
<p>{{ index (index .Site.Data.subdir $fileName) $keyInDataFile }}</p>

Thanks @yaythomas! Is there a way to do that using sub-directories? I’ve tried a number of variations and all I get is

error calling index: index of untyped nil

This works (if I move the file into /data/api/incidents.yaml):

{{ $fileName := "incidents" }}
{{ $data := (index .Site.Data.api $fileName) }}

This does not (where the file originally needs to be in /data/api/tickets/tenants/incidents.yaml):

{{ $fileName := "tickets/tenants/incidents" }}
{{ $data := (index .Site.Data.api $fileName) }}

I’ve tried forward slash, backslash, beginning with a slash, with extension, without. No bueno.

You gotta get nesting with them index-es. . .

{{ $fileName := "mydatafile" }}
{{ $keyInDataFile := "a" }}
{{ $subdir := "subdir" }}
<p>{{ index (index (index .Site.Data $subdir) $fileName) $keyInDataFile }}</p>

[edit:] Hmm, you know, could prob do something cute with a recursive template function that takes a slice that’ll traverse the child-collections by index like this. . . but whether that’s “easier” than writing out those nested indexes is up for debate.

1 Like

Ugh, I dunno if that’ll work. The problem is that there’s no guarantee how deep the file will be, I’m working with an openapi specification that has all the endpoints broken out into single files. The directory structure follows the EP path, so it could be /one/two it could be /one/two/three/four/five/six

Thanks for the help! Just out of curiosity if I continue to look further into writing a function for this… can you use any available Go function within the templates, such as string functions (thinking of Split() for example?

haha, yep, from what you’re describing you might well need to do the something cute I was hinting at.

To flesh it out a bit less cryptically, check out using an inline partial. https://gohugo.io/templates/partials/#inline-partials

you could use Hugo’s Split to get a collection of path elements to traverse/nest, and then recursively invoke the inline partial with something like this on the return:

  {{ return index $currentCollection $currentPathElement }}

No, not any Go function. The functions Hugo wraps for you/lets you use are here:

1 Like

Thanks, that’s got me head in the right direction at least. I was hellbent earlier on finding a simple string method, but I suppose this way I’ll learn more about what I can do with Hugo. :slight_smile:

1 Like