Jekyll - Get all posts that are in multiple categories
Asked Answered
W

3

5

I want to loop over all posts that are assigned category "foo" and category "bar" ..

{% for post in site.categories.foo and in site.categories.bar %}

Is this possible?

In my case "foo" as a "parent" category to "bar" ... /foo/bar/_posts

Thanks

Workable answered 14/4, 2014 at 2:15 Comment(0)
H
4

Instead of looking through every post and matching with an or, you can filter by the first tag and then look for the second (and third, fourth, fifth...) tags:

{% for post in site.categories.fizz%}
    {% if post.categories contains "buzz" and post.categories contains "bang" %}
         <!--post has categories fizz AND buzz AND bang-->
        <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endif %}
{% endfor %}

This is a little more efficient than iterating over every single post, and it sets up an and relationship instead of an or relationship.

Hordein answered 9/6, 2016 at 17:37 Comment(0)
E
3

It is fully possible: loop over all posts, and then select the wanted posts:

{% for post in site.posts %}
    {% if post.categories contains "foo" or post.categories contains "bar" %}
        <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endif %}
{% endfor %}
Equipage answered 14/4, 2014 at 8:52 Comment(5)
I tried this but then my forloop.index gets off which I'm using to write some separator elements.Workable
And in my use case it would be an "and" not an "or"Workable
Could you please discribe how your posts are actually stored, and how your categories are defined?Equipage
I did. They are organized by path as shown in the original question.Workable
Yes, but how your YALM looks like? Is there something specific in your _config.yml about url ?Equipage
K
0

Using the Where Expression filter in Jekyll.

Jekyll Liquid Filter Docs

Where Expression, Select all the objects in an array where the expression is true. 3.2.0

{{ site.members | where_exp:"item", "item.projects contains 'foo'" }}

So on my site I did:

_includes/clippings.html
...
{% capture _filter %}item.tags contains '{{ include.tag }}'{% endcapture %}

{% for clip in site.clippings | where_exp: 'item', _filter %}
  {{ clip.do_stuff }}
  # more html and stuff
{ endfor }
{% include clippings.html tag='foo' %}

In this case I need to specify the filter tag dynamically. And clippings is just a collection like posts.

If you want to filter by multiple static tags you could do something like:

{% for post in site.posts | where_exp: 'item', "item.tags contains 'foo'" | where_exp: 'item', "item.tags contains 'bar'" %}
  {{ post.do_stuff }}
{ endfor }

If you want to do multiple dynamic filter tags then you will need to do something similar to the capture stuff I did above.

I have not tested this, but it should filter posts by an arbitrary amount of filter tags.


{% assign posts = site.posts %}
{% filter_tags = 'foo, bar, buzz' | slipt: ', ' %}

{% for tag in filter_tags %}
  {% capture _filter %}item.tags contains '{{ tag }}'{% endcapture %}
  {% assign posts = posts | where_exp: 'items', _filter %}
{% endfor %}

{% for post in posts %}
  {{ post.do_stuff }}
{% endfor %}

However looping over the whole thing once and checking each post might be more efficient at that point.

Kehoe answered 6/7, 2021 at 0:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.