Range can’t iterate over array

Environment Details

Hugo Static Site Generator v0.55.4 linux/amd64 BuildDate: 2019-04-25T10:10:44Z
GOOS="linux"
GOARCH="amd64"
GOVERSION="go1.12.2"

Error

I’m trying to create a data template to range over a JSON array in one of my ~/data files, but I’m stuck on the following error:

... execute of template failed: template: ... at <$quote>: range can't iterate over $.Site.Data.quotes.person.lines

… but what am I doing wrong to keep Hugo from iterating over what is, in fact, an array?

JSON Schema

From ~/data/quotes.json, clearly showing person.lines as an array:

{
    "person": {
        "lines": [
            "first line of trenchant prose",
            "second line",
            "don’t forget this line",
            "long-winded author",
            "last line."
        ]
    }
}

I’m referencing the person key as a front matter value in my templates and making it the context inside the partial template (the template throwing the error).

Template

<blockquote>
    {{ $quote := . }}
    {{ range (printf "$.Site.Data.quotes.%s.lines" $quote) }}            
        <span>{{ . }}</span>
    {{ end }}
</blockquote>

I don’t think it’s a context issue, since I’m able to access the $quote with the dot, as suggested by the error text. So, I’m stumped.

Please advise.

Thanks for your help.

You need to do something like:

$q := index $.Site.Data.quotes  $quote
with $q 
range .lines
end

I omitted the brackets because of laziness.

Thanks for sticking with me here, @bep.

So, I just tried this:

{{ $quote := . }}                               
{{ $q := index $.Site.Data.quotes $quote }}              
{{ with $q }}                                                       
    {{ range .lines }}                                              
        {{ . }}                                                     
    {{ end }}                                                       
{{ end }}

And the new error seems to suggest a dot context issue . . . ? (Which I’d be at a loss to rectify if I can access the variable with .)

at <$.Site.Data.quotes>: can't evaluate field Site in type string

Did I miss something?

I assume “$” is in fact a string (maybe the same as “.”?), in the context you’re using this snippet. Try using the global “site” variable instead:

{{ $q := index site.Data.quotes $quote }}
2 Likes

@madispe, astounding! … and strange.

I cannot imagine a future in which I would have come to that solution on my own, let alone that it would actually work.

1 Like

Glad you got it working!

You might get more context (heh) from this documentation paragraph regarding contexts:

$ has special significance in your templates. $ is set to the starting value of . (“the dot”) by default.

BUT

From within the partial, $.Var is equivalent to .Var .

(source)

In your case it tried to access "your quote content as string".Site.Data.quotes, which failed obviously.

Basically just try to use the global site variable everywhere :stuck_out_tongue:

2 Likes

Thanks! :slight_smile: