Help regarding range loop and data to create a grid system

Hello to everyone.

I’m using Hugo for the first time and I’m coming from Jekyll, so please bear with me :slightly_smiling:

In Jekyll I was able to loop through a data file and retrieve the values and make a grid like this:

{% for member in site.data.team %}
  {% assign name = member.name %}
  {% assign description = member.description %}
  {% cycle 'add row' : '<div class="row">', nil %}
    <div class="col-xs-12 col-sm-4 {% cycle 'add offset' : 'col-sm-offset-2', nil %}">
        <div class="thumbnail">
            <img src="/assets/img/team/{{ name | replace: ' ', '_' }}.png" alt="{{ name }} Photo" width="131" height="130">
            <div class="caption">
                <h3 class="text-center">{{ name }}</h3>
                <p>{{ description }}</p>
            </div>
        </div>
    </div>
  {% cycle 'end row' : nil, '</div>' %}
  {% cycle 'end offset' : nil, nil %}
{% endfor %}

Now, with Hugo, I had to convert the YAML data file to TOML because I was getting a marshalling error. That is OK, I can live with that. Here’s my team.toml just in case I’ve made something wrong here:

[[member]]
name = "First Last"
description = "Foo dev"

[[member]]
name = "FirstName LastName"
description = "Bar dev"

And this is what I have in team.md:

{{ range .Site.Data.team.member }}
    <div class="thumbnail">
        <img src="/assets/img/team/{{ .name | replace ' ' '_' }}.png" alt="{{ .name }} Photo" width="131" height="130">
        <div class="caption">
            <h3 class="text-center">{{ .name }}</h3>
            <p>{{ .description }}</p>
        </div>
    </div>
{{ end }}

And here’s my directory structure. Maybe I’m missing a template file?

 Directory of C:\Users\xmr\Desktop\project-hugo

06/06/2017  13:09    <DIR>          .
06/06/2017  13:09    <DIR>          ..
06/06/2017  13:06             1.630 config.yml
06/06/2017  13:06    <DIR>          content
06/06/2017  09:49    <DIR>          data
06/06/2017  12:53    <DIR>          layouts
05/06/2017  11:55    <DIR>          static

 Directory of C:\Users\xmr\Desktop\project-hugo\content

06/06/2017  13:06    <DIR>          .
06/06/2017  13:06    <DIR>          ..
06/06/2017  08:37             1.384 404.md
06/06/2017  13:04             3.612 team.md

 Directory of C:\Users\xmr\Desktop\project-hugo\data

06/06/2017  09:49    <DIR>          .
06/06/2017  09:49    <DIR>          ..
06/06/2017  10:02             1.696 team.toml

 Directory of C:\Users\xmr\Desktop\project-hugo\layouts

06/06/2017  12:53    <DIR>          .
06/06/2017  12:53    <DIR>          ..
05/06/2017  19:46                52 index.html
06/06/2017  12:53    <DIR>          partials
05/06/2017  12:17               125 robots.txt
05/06/2017  20:04               920 sitemap.xml
06/06/2017  13:05    <DIR>          _default

 Directory of C:\Users\xmr\Desktop\project-hugo\layouts\partials

06/06/2017  12:53    <DIR>          .
06/06/2017  12:53    <DIR>          ..
06/06/2017  10:24             4.334 footer.html
06/06/2017  09:42             1.871 header.html
05/06/2017  19:16             1.051 nav.html

 Directory of C:\Users\xmr\Desktop\project-hugo\layouts\_default

06/06/2017  13:05    <DIR>          .
06/06/2017  13:05    <DIR>          ..
05/06/2017  21:18                 0 list.html
06/06/2017  13:05                72 single.html

 Directory of C:\Users\xmr\Desktop\project-hugo\static

05/06/2017  11:55    <DIR>          .
05/06/2017  11:55    <DIR>          ..
05/06/2017  11:55    <DIR>          assets

Now with this, I get the exact html code output; it’s like Hugo doesn’t parse that and just copies it as is.

How can I achieve the same with Hugo?

Thanks in advance!

You can not have template syntax directly in content files (there are shortcodes, but that isn’t relevant here, I think). There are several ways to get to where you want, but I suggest you have a look at template files.

1 Like

OK, I managed to solve the issue with a shortcode and checking for odd/even value.
Perhaps it’s not the best solution but it works…

{{ range $i, $member := .Site.Data.team.member }}
{{ if modBool $i 2 }}
<div class="row">
{{ end }}
    <div class="col-xs-12 col-sm-4{{ if modBool $i 2 }} col-sm-offset-2{{ end }}">
        <div class="thumbnail">
            <img src="/assets/img/team/{{ replace $member.name " " "_" }}.png" alt="{{ $member.name }} Photo" width="131" height="130">
            <div class="caption">
                <h3 class="text-center">{{ $member.name }}</h3>
                <p>{{ $member.description }}</p>
            </div>
        </div>
    </div>
{{ if not (modBool $i 2) }}
</div>
{{ end }}
{{ end }}

I wonder if this could be improved but it’s micro optimization anyway.

Thanks for the prompt reply! I really appreciate the support since I will probably have to ask more questions I dig into Hugo more and more :slightly_smiling:

Actually, the above works, but there’s the case where one has even members and </div> won’t be output :confused:

I tried playing with len but it seems I can’t make the check to work…

{{ if (not (modBool $i 2)) or (eq (len $member) 6)}}
</div>
{{ end }}

or doesn’t work like that. Use it as or x y:

{{ or (not (modBool $i 2)) (eq (len $member) 6) }}

Thanks!

I managed to solve the issue with this:

{{ $len := len .Site.Data.team.member }}
{{ range $i, $member := .Site.Data.team.member }}
{{ if modBool $i 2 }}
<div class="row">
{{ end }}
    <div class="col-xs-12 col-sm-4{{ if modBool $i 2 }} col-sm-offset-2{{ end }}">
        <div class="thumbnail">
            <img src="/assets/img/team/{{ replace $member.name " " "_" }}.png" alt="{{ $member.name }} Photo" width="131" height="130">
            <div class="caption">
                <h3 class="text-center">{{ $member.name }}</h3>
                <p>{{ $member.description }}</p>
            </div>
        </div>
    </div>
{{ if (or (not (modBool $i 2)) (eq (add $i 1) $len)) }}
</div>
{{ end }}
{{ end }}

len seems to be 1-based since it’s always off by 1 so I had to use add.

3 Likes