Range with Variable from Shortcode

I’m sorry if this is sort of rudimentary, but I cannot figure out the correct syntax.

I have a YAML file with camera information:

/data/cameralist.yml

cameras:

    camera1:
        model: xa
        manufacturer: olympus
        lens: F.Zuiko f=35mm
        format: 35mm     
          
    camera2:
        model: accura infinity
        manufacturer: olympus
        lens: Olympus Lens 38-80mm
        format: 35mm

I have a shortcode setup, camera_info.html.

{{< camera_info data="camera2" >}}

inside camera_info.html, I have a really simple range. I want to use the variable sent over from shortcode page to specify WHICH entry in the yaml file to range through.

{{ $caminfo := .Params.data }}


	<ul>
	{{ range .Site.Data.cameralist.cameras.($caminfo) }}	
		<li>{{ . }}
	{{ end }}  
  	</ul>

This is how I thought this should work but it throws an error. Every iteration i’ve tried has given me an error and I cannot find an example of this. Maybe I have a misguided idea of how to do this so I’m looking for some help. Appreciate it!

Very close. Try this:

{{ $caminfo := .Params.data }}
<ul>
{{ range $k, $v := (index .Site.Data.cameralists.cameras $caminfo) }}
	<li>{{ $k }}: {{ $v }}</li>
{{ end }}
</ul>
3 Likes

That’s amazing, thank you so much for your help. I did not know that $k & $v would automatically pull in the key and value of the map, that’s great to learn. Thank you!

One other question, when it returns the results they are in sorted into alphabetical order. Is there anyway to specify that I would like them in the order they were entered into the YAML?

You’re welcome.

$k and $v can be arbitrarily named. I usually name them $key / $value or just $k / $v. If you don’t assign any variables, the context (the dot .) contains only the value.

Your requirement makes it a bit more complex. As far as I know, making the yaml available to Hugo destroys the order in your case.

But if you know the field names in advance, you could code the order into your shortcode like:

{{ $caminfo := .Params.data }}
<ul>
{{ $order := slice "model" "manufacturer" }}
{{ $camera := index .Site.Data.cameralists.cameras $caminfo }}
{{ range $order }}
	{{/* print all known fields in the desired order */}}
	{{ $k := . }}
	{{ $v := index $camera $k }}
	<li>{{ $k }}: {{ $v }}</li>
{{ end }}
{{ range $k, $v := $camera }}
	{{ if not (in $order $k) }}
	{{/* print remaining fields not contained in the desired order;
	by that, additional fields unknown at the time of writing this
	shortcode are still printed at the end of the list */}}
	<li>{{ $k }}: {{ $v }}</li>
	{{ end }}
{{ end }}
</ul>
2 Likes

Great to know that Hugo injests and "destroys’ the order of the yaml, that makes understand how this is working a little easier.

And your solution is actually a pretty great way to feature this because there are only 6 or 7 fields that I KNOW i’m going to include, and then other cameras were going to have more on a per-feature basis. This lets me continue to just update the YAML file instead of hardcoding each page, which was the other option. I figured if I did it this way, I could also link specific classifications to one other like a cheap version of a ‘many-to-many’ database.

Thanks again, appreciate you taking the time to explain this.

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.