YAML for datapage: how to organize?

Hello everyone,

first of all thank you for this great software and helpful forum.

I have a file data/testfile.yaml:

- date: 1905
  title: some event
- date: 1905
  title: some other event
- date: 1910
  title: something always happens

I have a shortcode themes/<theme name>/layouts/shortcodes/read-testfile.html:

{{ range sort site.Data.history "date" }}
  <h2>{{ .date }}</h2>
  <h3>{{ .title | markdownify }}</h3>
{{ end }}

I get the expected output.
I get an h2 heading for each date and an h3 heading for each title.

I would like the date heading to be output only once, even if there are multiple titles.
So using the above example

<h2>1905</h2>
<h3>some event</h3>
<h3>another event</h3>
<h2>1906</h2>
<h3>something always happens</h3>
  • How do I need to build my testfile.yaml?
  • How can I query it in my shortcode?

Full of hope for beginner friendly hints.

Many greetings

Original text in German, see below.
Translated with DeepL Translate: The world's most accurate translator (free version)


Hallo miteinander,

zunächst vielen Dank für diese großartige Software und dieses hilfreiche Forum.

Ich habe eine Datei data/testdatei.yaml:

- datum:   1905
  title:   irgendein Ereignis
- datum:   1905
  title:   ein anderes Ereignis
- datum:   1910
  title:   irgendwas passiert immer

Ich habe einen Shortcode themes/<themename>/layouts/shortcodes/read-testdatei.html:

{{ range sort site.Data.geschichte "datum" }}
  <h2>{{ .datum }}</h2>
  <h3>{{ .title | markdownify }}</h3>
{{ end }}

Ich erhalte den erwarteten Output.
Ich bekomme fĂĽr jedes datum eine h2-Ăśberschrift und fĂĽr jeden title eine h3-Ăśberschrift.

Ich möchte gerne, dass die datum-Überschrift nur einmal ausgegeben wird, auch wenn es mehrere title gibt.
Also an obigem Beispiel

<h2>1905</h2>
<h3>irgendein Ereignis</h3>
<h3>ein anderes Ereignis</h3>
<h2>1906</h2>
<h3>irgendwas passiert immer</h3>
  • Wie muss ich meine testdatei.yaml aufbauen?
  • Wie kann ich sie in meinem Shortcode abfragen?

Voller Hoffnung auf anfängerfreundliche Hinweise.

Viele GrĂĽĂźe

Originaltext in Deutsch, siehe unten

I’m sorry I’m on mobile so I can’t really help with code sample at the moment but I would think the best way would be to setup your data file

- date:
  - year: 1905
  - title:
    - something happened
    - something else
- date:
  - year: 1906
  - title:
    - nothing
- date:
Etc

Then you range through the dates, apply the year for header 2 and range through the titles applying header 3. If there is only one title then it only does one.

1 Like

Hello gaetawoo,

thank you for your helpful hint regarding the structure of the YAML file.

With the shortcode

{{ range site.Data.testfile }}
{{ range .date }}
{{ if .year }}<h2>{{ .year }}</h2>{{ end }}
{{ if .title }}<h3>{{ .title }}</h3>{ end }}
{{ end }}
{{ end }}

I get the output

<h2>1905</h2>
<h3>[something happened something else]</h3>
<h2>1906</h2>
<h3>[nothing]</h3>

Now I want to have a h3 heading for each .title, not for the whole array(?).

The shortcode

{{ range site.Data.testfile }}
{{ range .date }}
{{ if .year }}<h2>{{ .year }}</h2>{ end }}
{{ range .year }}
{{ if .title }}<h3>{{ .title }}</h3>{ end }}
{{ end }}
{{ end }}
{{ end }}

leads to the error message

"D:\DEVELOPMENT\hugo\sites\ra-master\content\showcase\datensaetze.md:49:1": failed to render shortcode "data-testfile": failed to process shortcode: "D:\DEVELOPMENT\hugo\sites\ra-master\themes\ra-master\layouts\shortcodes\data-testfile. html:11:9": execute of template failed: template: shortcodes/data-testfile.html:11:9: executing "shortcodes/data-testfile.html" at <.year>: range can't iterate over 1905

What am I doing wrong?

Many greetings


Hallo gaetawoo,

vielen Dank fĂĽr deinen hilfreichen Hinweis bzgl. des Aufbaus der YAML-Datei.

Mit dem Shortcode

{{ range site.Data.testdatei }}
{{ range .date }}
{{ if .year }}<h2>{{ .year }}</h2>{{ end }}
{{ if .title }}<h3>{{ .title }}</h3>{{ end }}
{{ end }}
{{ end }}

erhalte ich den Output

<h2>1905</h2>
<h3>[something happened something else]</h3>
<h2>1906</h2>
<h3>[nothing]</h3>

Nun möchte ich für jeden .title eine h3-Überschrift haben, nicht für das gesamte Array(?).

Der Shortcode

{{ range site.Data.testdatei }}
{{ range .date }}
{{ if .year }}<h2>{{ .year }}</h2>{{ end }}
{{ range .year }}
{{ if .title }}<h3>{{ .title }}</h3>{{ end }}
{{ end }}
{{ end }}
{{ end }}

fĂĽhrt zu der Fehlermeldung

"D:\DEVELOPMENT\hugo\sites\ra-master\content\showcase\datensaetze.md:49:1": failed to render shortcode "data-testdatei": failed to process shortcode: "D:\DEVELOPMENT\hugo\sites\ra-master\themes\ra-master\layouts\shortcodes\data-testdatei.html:11:9": execute of template failed: template: shortcodes/data-testdatei.html:11:9: executing "shortcodes/data-testdatei.html" at <.year>: range can't iterate over 1905

Was mache ich falsch?

Viele GrĂĽĂźe

The reason you are getting your error is because you are trying to iterate over year which is not an array, and title isn’t part of year, it’s part of date. So something like this might work (i’m not able to test it):

{{ range site.Data.testfile }}
  {{ range .date }}
    {{ with .year }}<h2>{{ . }}</h2>{ end }}
    {{ range .title }}
      {{ with .title }}<h3>{{ . }}</h3>{ end }}
    {{ end }}
  {{ end }}
{{ end }}

Title is the array over which you iterate, not year. Both title and year are children of date, they are not otherwise directly related.

Hello gaetawoo,

thanks again for your generous support.

Your shortcode

{{ range site.Data.testfile }}
  {{ range .date }}
    {{ with .year }}<h2>{ . }}</h2>{ end }}
    {{ range .title }}
      {{ with .title }}<h3>{ . }}</h3>{ end }}
    {{ end }}
  {{ end }}
{{ end }}

leads to the following error message

"D:\DEVELOPMENT\hugo\sites\ra-master\content\showcase\datensaetze.md:49:1": failed to render shortcode "data-testdatei": failed to process shortcode: "D:\DEVELOPMENT\hugo\sites\ra-master\themes\ra-master\layouts\shortcodes\data-testdatei.html:26:14": execute of template failed: template: shortcodes/data-testdatei.html:26:14: executing "shortcodes/data-testdatei.html" at <.title>: can't evaluate field title in type interface {}

Too bad, found your code so clear and logical when reading it, I don’t understand the error message.

Do you have another idea for me?
Either way, thank you and best regards


Hallo gaetawoo,

noch einmal vielen Dank fĂĽr deine groĂźzĂĽgige UnterstĂĽtzung.

Dein Shortcode

{{ range site.Data.testdatei }}
  {{ range .date }}
    {{ with .year }}<h2>{{ . }}</h2>{{ end }}
    {{ range .title }}
      {{ with .title }}<h3>{{ . }}</h3>{{ end }}
    {{ end }}
  {{ end }}
{{ end }}

fĂĽhrt zu folgender Fehlermeldung

"D:\DEVELOPMENT\hugo\sites\ra-master\content\showcase\datensaetze.md:49:1": failed to render shortcode "data-testdatei": failed to process shortcode: "D:\DEVELOPMENT\hugo\sites\ra-master\themes\ra-master\layouts\shortcodes\data-testdatei.html:26:14": execute of template failed: template: shortcodes/data-testdatei.html:26:14: executing "shortcodes/data-testdatei.html" at <.title>: can't evaluate field title in type interface {}

Schade, fand deinen Code beim Lesen so klar und logisch, die Fehlermeldung verstehe ich nicht.

Hast du noch eine Idee fĂĽr mich?
So oder so, Danke und viele GrĂĽĂźe

I’m sorry, i do see a syntax bug in what i posted before.
The inner with .title is wrong in this context

Maybe the following.

{{ range site.Data.testfile }}
  {{ range .date }}
    {{ with .year }}<h2>{ . }}</h2>{ end }}
    {{ range $title := .title }}
      {{ with $title }}<h3>{ . }}</h3>{ end }}
    {{ end }}
  {{ end }}
{{ end }}

I’m saving the context of the inner range to a variable and using with with the variable. The previous way was using with with something that didn’t exist.

Hello gaetawoo,

your shortcode produces neither output nor error message. :frowning:

Thanks again and best regards

data/testfile.yaml

- date: 1905
  title: some event
- date: 1905
  title: some other event
- date: 1910
  title: something always happens

layouts/shortcodes/read-testfile.html

{{ $dates := slice }}
{{ range site.Data.testfile }}
  {{ $dates = $dates | append .date }}
{{ end }}
{{ $dates = $dates | uniq | sort }}

{{ range $dates }}
  <h2>{{ . }}</h2>
  {{ range where site.Data.testfile "date" . }}
    <h3>{{ .title }}</h3>
  {{ end }}
{{ end }}

7 Likes

Yea, this is definitely the way to do it. Thanks @jmooring

I finally got a chance to test this out. I’m using a fresh, totally bare bones layout template.

My last suggestion works on my end. It produces the expected/desired html.

It’s not as pretty on the data file side as @jmooring nor as elegant on the templating side… but it does work.

/data/testfile2.yaml

- date:
  - year: 1905
  - title:
    - something happened
    - something else
- date:
  - year: 1906
  - title:
    - nothing

template

try3
{{ range site.Data.testfile2 }}
  {{ range .date }}
    {{ with .year }}<h2>{{ . }}</h2>{{ end }}
      {{ range .title }}
        {{ with . }}<h3>{{ . }}</h3>{{ end }}
      {{ end }}
  {{ end }}
{{ end }}

<br>

try4
{{ range site.Data.testfile2 }}
  {{ range .date }}
    {{ with .year }}<h2>{{ . }}</h2>{{ end }}
      {{ range $title := .title }}
        {{ with $title }}<h3>{{ . }}</h3>{{ end }}
      {{ end }}
  {{ end }}
{{ end }}

So while I would still use @jmooring solution, just for educational sake, it does work. I’m not sure why you would have seen no output and no error. And it’s valuable to put in some debugging {{ print "test" }} or something statements in the code to see what is getting processed and when. Or {{ warnf "something" }} to have it write to the output console.

Also, i’m not doing it in a shortcode, i’m doing it in the actual layout template so while that might be a difference, given the code and the scope, i don’t see how it could be.

EDIT: Below

Also the below works:

testfile3.yaml

- date: 1905
  title:
    - something happened
    - something else
- date: 1906
  title:
    - nothing

template

try6
{{ range $item := site.Data.testfile3 }}
  {{ with .date }}<h2>{{ . }}</h2>{{ end }}
      {{ range $item.title }}
        {{ with . }}<h3>{{ . }}</h3>{{ end }}
      {{ end }}
{{ end }}

The outputs are all the same as pictured above.

1 Like

Hello jmooring,

thanks a lot for your code.
Could try it last night, it works.
Your code helped me a lot.

Please contradict me if I misunderstand the “slice part” of your code.

{ $dates := slice }}: slice creates a new array $dates.
{ $dates = $dates | append .date }}: Append to the array $dates the value of the current record .date.
{ $dates = $dates | uniq | sort }}: array is sorted and duplicate values are removed

Many greetings

Hello gaetawoo,

thanks a lot for checking your code.
No idea why that one didn’t work for me.
Will probably not have time to deal with it until the weekend unfortunately.
I especially like try6 because of the clear structure of the underlying testfile3.yaml.

Thank you very much for your support/help and especially for the explanatory words about the code.

Many greetings

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