Looping through a sub collection or sub directory in a collection

I’d like to be able to loop through every page in a sub directory (what I’m calling a sub collection) that’s inside a collection, but I’m having trouble outputting the page/s.

My collection name:
_pizza

My sub collection/directory name:
_pizza/articles

The objective is to output every page that’s inside articles and present a list. The md file is located at _pizza/articles/index.md

The code:


    {% for page in site.pizza.articles limit:33 %}
    {% if page.url == ‘/pizza/articles/’ %}
  • {{ page.headline }}

  • {% endif %}
    {% endfor %}

Unfortunately, this does not output the pages inside pizza.articles. Is there another way to do this? Please let me know if there is a more appropriate way to handle this or if I can explain this better. Thank you for the help in advance.

when you do a for loop, the word after for is a key for the rest of it. page is already a thing, so using it in this context is probably getting you the current files url right?

I always use item as my key - for item in site.whatever, item.url, item.title etc. Not sure key is the correct word.

Not sure that is your problem or that the rest of your code is correct, just something that I think is incorrect.

1 Like

Thanks, that’s good to know. I have made the change in my files.
Unfortunately, that change didn’t let me loop through subdirectory/sub collection. I simplified the example a bit more.

{% for item in site.pizza.articles %}
{{ item.title }}
{% endfor %}
  • There are *.md files in the articles directory

not sure about sub folders in a collection.

This post on SO seems to say that they may work like a category - posts are treated this way, and posts are a collection item so it may work. Looks like you actually need to specify the category in the front matter as well. You could also just make your own custom front matter variable. Also looks like you can test if the path contains articles.

Second answer here:

Thanks for the article. I actually posted a correction comment at the end of the thread. This is the best way I could work it up, just wish it was easier to drill done to the specific directory rather than filter it with conditional. That could get real laborious given really deep/nested directories. Either way, I think this is what you were saying about using the URL method.

<ul>
	{% for item in site.pizza limit:33 %}
	{% if item.url contains 'articles' and item.url != '/pizza/' and item.url != '/pizza/articles/' %}
	<li><a href="{{ item.url }}">{{ item.headline }}</a></li>
	{% endif %}
	{% endfor %}
</ul>

yes, that is about it. I only use collections in a minimal manner, someone else may have more insight.

1 Like

Thanks for the help and happy new year. :smiley::fireworks::sparkles::tada:

If someone else out there has deeper insight on collections and accessing sub directories, please let us know – thank you.

I believe the issue is Collection documents aren’t quite on par with site.posts. They don’t have support for categories or tags like _posts, which means you can’t use some like site.collection_name.category_name to loop through.

Same thing goes for subfolders. Typical behavior is Jekyll takes whatever the subfolder’s name is and assigns that as a category to the posts beneath it… that doesn’t happen with collections.

What you can do instead is add some sort of identifier variable to collection documents’ front matter so you can group them.

To take your example above, in all of your _pizza/articles/ files you could add something like grouped_by: articles in their YAML Front Matter.

Then using the where filter you can pull out just those documents. You’ll need to use assign first as the where filter doesn’t work when applied on a for loop. A simple example of how that would be coded:

{% assign pizza_articles = site.pizza | where:"grouped_by","articles" %}
<ul>
  {% for article in pizza_articles limit:33 %}
    <li><a href="{{ article.url | relative_url }}">{{ article.title }}</a></li>
  {% endfor %}
</ul>
2 Likes

also the front matter could probably be set as a default in the config file vs in every file, but again I don’t use that much either but I think path is one of the things you can use to set a default so maybe that would work.

@mmistakes Very cool. So this loops through all with grouped_by articles, stuffs them in an array. Then, it uses that assignment in the for loop. Thanks.

Also, nice to know that Collection docs don’t have the same support for categories as posts. Maybe in the future it will. :crossed_fingers:t4:

@rdyar Yes, that sounds like it could also reduce the amount of work stuffing the category or group in the defaults array. I assume you mean this:

_config.yml:

defaults:
  - scope:
      path: "" # an empty string here means all files in the project
    values:
      theme-color: ff3310

I guess the question would be how? Another item in the array?

in the path there you could try putting the full path - pizza/articles or whatever and see if that combined with MM’s idea would work.

For what it’s worth I found this thread on jekyll/jekyll discussing sub directories (categories) in collections if you wanted to weigh in there.

https://github.com/jekyll/jekyll/issues/6030