mike
mike

Reputation: 1906

How can I loop through a YAML collection with child collection in Lquid or Javascript in eleventy?

How do I take a YAML list with nested lists and output the nested items?

---
- fruit
  - banana
  - apple
  - orange
- vegetable
  - lettuce
  - broccoli
  - carrots
- bread
- cheese
- meat
  - beef
  - turkey
  - chicken

Then

<h1>Groceries</h1>
{% for item in groceries %}
{% comment %}
1. capture item
2. test for nested list
3. render nested items
{% endcomment %}
{{ item }}
{% endfor %}

Does Liquid have a filter to check for and iterate through nested lists?

Should I create a custom Javascript filter with a callback?

Upvotes: 0

Views: 770

Answers (2)

Raymond Camden
Raymond Camden

Reputation: 10857

Ok, I want to add another answer. I may remove my first one but want to leave it for now. So going with this front matter which is a bit closer to your original I think:

---
layout: main
groceries:
    - fruit
        - banana
        - apple
        - orange
    - vegetable
        - lettuce
        - broccoli
        - carrots
    - bread
    - cheese
    - meat
        - beef
        - turkey
        - chicken
---

I then did this:

{% for type in groceries %}
    {% assign items = type | split: " - " %}
    {% assign header = items[0] %}
    <h2>{{ header }}</h2>
    {% if items.length > 1 %}
        <ul>
        {% for item in items %}
            {% unless forloop.first %}
            <li>{{item}}</li>
            {% endunless %}
        {% endfor %}
        </ul>
    {% endif %}
    <p>
{% endfor %}

In the loop, items is an array containing the top level item and any children. So the first item is always the main thing (fruit, veggie, meat). If we have 2 or more items, it means we have a 'sublist', and you can see how I loop over them and skip the first item.

Thoughts?

Upvotes: 1

Raymond Camden
Raymond Camden

Reputation: 10857

I'm really unsure of this, but, it seems to work. First, I modified your front matter a bit:

---
layout: main
groceries:
    - fruit:
        - banana
        - apple
        - orange
    - vegetable:
        - lettuce
        - broccoli
        - carrots
    - bread:
    - cheese:
    - meat:
        - beef
        - turkey
        - chicken
---

Notice I've added : at the top level items including those for 'empty' types. I then iterated like so:

{% for type in groceries %}
    {% for items in type %}
        <h2>{{ items[0] }}</h2>
        {% for item in items[1] %}
            {{ item }}<p>
        {% endfor %}
    {% endfor %}
{% endfor %}

The three levels of looping there three me. type ends up looking like: {"fruit":[ array of stuff]}

So maybe my front matter isn't good?

Upvotes: 0

Related Questions