How to best display all images from a folder

hello, here is my conundrum.

my data files consist of exhibitions with info such as:

title: ABD
media:
  images:
    image: 01.jpg
    image: 02.jpg
    image: 03.jpg
    image: 04.jpg
    image: 05.jpg

etc.

within the branch bundle layout file (list.html) i have:

{{ partial "header" . }} 
{{ .Content }}
<div class="gallery">
</div>
{{ partial "footer" .}} 

within the _index.md file i have:

---

---

# bla bla bla

(nothing, so far)

I’d like to display every image i have in the data file within the css class “gallery”

All images are situated within the branch bundle, in a folder called “images”

Now, I know the data file layout i have may not be the most elegant: so please suggest what I can do?

You could range through all images in your page bundle, e.g.

{{ range .Resources.ByType "image" }}

Then within that range, range through your data file: if the .Name of the page bundle image equals the .image in your data file, then display it.

the image URLs are in the data file. should i put them in the _index.md file in the front matter?

i figured, if i put them in the data file, i could use them elsewhere in the site…

here is what i tried from your suggestion, in the branch bundle list.html layout file

{{ range .Resources.ByType "image" }}
	{{ range .Site.Data.shows }}

	{{ end }}
{{ end }}

but the problem is i want this to be a generic list.html, since i have many exhibitions, so how do i tell the layout file to extract THIS particular set of images?

hope i am making sense…

You could specify the data filename in your front matter, then grab that in your template. Something like:

{{ $data := index .Site.Data .Params.dataFilename }}
{{ range $data }}
...

i know this is totally wrong, please help:

in _index.md:

---
dataFile: XYZ
---

in data file XYZ.yaml:

media:
  images:
    image: 01.jpg

in list.html:

{{ partial "header" . }} 
{{ .Content }}

{{ $data := index .Site.Data .Params.dataFile }}


<ul class="gallery">
{{ range .Resources.ByType "image" }}
	
	{{ range $data }}

		{{ if eq .Name  }}

			<li><img src="{{ .images/image }}" /></li>



	{{ end }}
{{ end }}
</ul>

{{ partial "footer" .}}

argh
help

You’re close. Since you do a range within a range, you have to grab the .Name before the context changes.

This will get you closer (if not all the way there). I’ll let you handle the rest from here – it’ll be beneficial for you to understand.

{{ $data := index .Site.Data .Params.dataFile }}
{{ range .Resources.ByType "image" }}
  {{ $name := .Name }}
  {{ range $data }}
    {{ $img := .images.image }}
    {{ if eq $name $img }}
      <!-- Create your <img> element here -->
    {{ end }}
  {{ end }}
{{ end }}

doing:

<ul class="gallery">
	{{ $data := index .Site.Data .Params.dataFile }}
	{{ range .Resources.ByType "image" }}
	  {{ $name := .Name }}
	  {{ range $data }}
    	{{ $img := .media.images.image }}
	    {{ if eq $name $img }}
	    	<li><img src="$img" /></li>
	    {{ end }}
	  {{ end }}
	{{ end }}
</ul>

results in an error:

Error while rendering "section" in "": template: shows/list.html:5:13: executing "shows/list.html" at <index .Site.Data .Pa...>: error calling index: value is nil; should be of type string

?

The error message is clear

doing:

	{{ $data := index .Site.Data ".Params.dataFile" }}

does away with the error, but surely this is wrong?

i don’t see a “toString” funciton anywhere in the reference, how do i pass .Params.dataFile as a string?

i believe this is correct:

	{{ $data := index .Site.Data (string .Params.dataFile) }}

but no images are matched, and the ul remains unpopulated … please help?

datafile should be a string! You can write it as string too

---
dataFile: "XYZ"
---

yeah but

---
dataFile: "XYZ"
---

with

	{{ $data := index .Site.Data .Params.dataFile }}

still gives me the same error…

Hi,

The reason you are getting error calling index: value is nil; should be of type string may be that .Params.dataFile may sometimes be returning nil.

This may happen if you don’t have .Params.dataFile defined in all your sections _index.md.

You could first check {{ if .Params.dataFile }} before calling {{ index .Site.Data .Params.dataFile }}

Or use a more specific layout (than list.html).

A few more points:

title: ABD
media:
  images:
    image: 01.jpg
    image: 02.jpg
    image: 03.jpg
    image: 04.jpg
    image: 05.jpg
  1. This is not the correct way of defining a list (assuming you intended to define a list). Here, images is a map with five image keys. You probably want something like this instead:
title: ABD
media:
  images:
    - 01.jpg
    - 02.jpg
    - 03.jpg
    - 04.jpg
    - 05.jpg

Or perhaps the following, which would give you an array of maps

title: ABD
media:
  images:
    - image: 01.jpg
    - image: 02.jpg
    - image: 03.jpg
    - image: 04.jpg
    - image: 05.jpg


  1. {{ range $data }} will range over all of XYZ.yaml, returning
map[images:map[...]]
ABD

You need to range over $data.media.images. Then depending on which of the two list styles above you choose, access the image name by {{.}} or {{image}}

{{ range $data.media.images }}
  <!-- if you use the first --> {{.}}
  <!-- if you use the second --> {{.image}}<br>
{{ end }}

thanks @pointyfar for that detailed reply, without being cryptic. i’m still running up against problems,

my layout is under “layouts/shows/list.html”:

{{ partial "header" . }} 
{{ .Content }}

<ul class="gallery">
	{{ $data := index .Site.Data.shows .Params.dataFile }}
	{{ range .Resources.ByType "image" }}
	  {{ $name := .Name }}
	  {{ range $data }}
    	{{ $img := .media.images }}
	    {{ if eq $name $img }}
	    	<li><img src=$img /></li>
	    {{ end }}
	  {{ end }}
	{{ end }}
</ul>

now this is still throwing up a

Error while rendering "section" in "": template: shows/list.html:5:13: executing "shows/list.html" at <index .Site.Data.sho...>: error calling index: value is nil; should be of type string

error, despite not having any other folder in “content/shows”

and my content is under “content/shows/XYZ/_index.md”:

---
dataFile: XYZ
---

also, my dataFile now looks like:

media:
  images:
    - 01.jpg
    - 02.jpg
    - 03.jpg

so i’m using the syntax you suggested, but clearly my loops are wrong

does it have to be

dataFile: XYZ.yml

or somesuch? of course, i tried that and no dice.

  1. Where is your data file (XYZ.yml) located? We have been working here on the assumption that it is under yoursite/data/XYZ.yml. If so then $data needs to be:
{{ $data := index .Site.Data .Params.dataFile }}

Note: not .Site.Data.shows

which is the equivalent of

{{ $data := index .Site.Data "XYZ" }}

  1. The error message actually gives you a hint:
error calling index: value is nil; should be of type string

When you call the index function, there is a nil value which should be a string. So to figure out which one that is, print out the two arguments you use:

{{ .Site.Data.shows }} {{ .Params.dataFile }}


  1. Once you sort that out,
{{ range $data }}
...

will probably not work. Refer to my previous reply (the long one, towards the end)


Read more about data templates here: https://gohugo.io/templates/data-templates/#the-data-folder


It would make it so much easier for us to help you if you actually had a sample project we can play with.

1 Like

Agreed with @pointyfar

@blablabla You ask many questions on this forum (which I encourage :+1: ), but each time you only provide minimal code snippets. Since others are volunteering their time to help you, the least you could do is take the time to create a small repo that reproduces your issue. It also fixes the “but it works on my computer” issues.

1 Like

thank you both. the website i’m making is for an art collective i work with. i have spoken with them, and am trying to find a way in which i can open-source it now. however, they don’t want these questions showing up in search results related to the collective. a robots.txt file won’t be enough, as discourse.gohugo.io gets indexed, so what can i do?

cheers

When making your sample repo, use dummy data/dummy names for things which have no relation to the real project

here it is:

anonymised as much as possible

all of your time and effort is very much appreciated, thank you so much