Only show category heading if there are blogposts with same category

Hi, if you have an idea how I can do this please share.

I have a lot of blog posts that have different categories that I want to sort by category. The categories are in markdown on the page where I’m writing this loop
So:

{% for category in page.categories %}
  {{ category.title }}

  {% for post in site.blog %}
    {% for blogcategory in blog.category %} 
      {% if blogcategory == category.title %}

        {% include blogpost %}

      {% endif %}
    {% endfor %}
  {% endfor %}
{% endfor %}

This is ofc within some div elements, but this is the logic. Now I want to insert an if statement that basically says:

{% if blogpost of certain category < 1 %}
  Don't show the title of that category

So I don’t want to show the empty categories, how can I write the logic and where should I put it. Since I’m printing out the titles at the very beginning I’m not sure how to connect to each categories length.

If you can get an array of posts of each category before you iterate it, you can use size (with dot notation) to get the array length.

{% assign category_posts = ... %}

{% if category_posts.size < 1 %}
{% endif %}

Then with the previous condition you could use continue to skip the current iteration and continue with the next one.

{% if category_posts.size < 1 %}
{% continue %}
{% endif %}

Obviously it would need to be before you print the category title and iterate the category_posts to list the articles.

I can’t share a working code since I don’t know what’s the structure of page.categories, site.blog or blog.category, or if they are real variables because it seems to be just placeholders.

1 Like

Do you have any ideas how I can get an array with categories that are used by the blogposts, but only once? I get an array with category: [a , a , a , b , c , c … ] and so the titles will repeat accordingly.

Use the uniq filter.

have a read through this … I did it recently

1 Like

unfortunately it doesn’t work with uniq since I realized that it won’t create one array with duplicates, but instead one array for each category (one word in each array), so it isn’t connected to each other… I tried to iterate only once with limit:1 but that didn’t work either… so now I have [a] [a] [b] [c] [c] etc… The thing is that I need to be inside my for loop because I need to compare different lists with each other to find matching result so I then can print only the categories that actually have posts. I manage to get rid of the categories that doesnt have posts, but the ones that have posts will be printed as many times as the amout of posts that one category have.

This is what I use to collect the number of posts for category:

{% assign count = site.posts | where_exp: ‘item’, ‘item.category contains cat’ | size %}

where cat is the category took from a loop, then you can test the count variable.

1 Like

What if you use the categories on the current post at strings
And you look up a category object with its title and posts. Then show the category if there are at least two posts in the category (current post and one other post).
Then you can show the category heading and the posts in it.

{% for cat in post.categories %} 
  {% assign category = site.categories[cat] %}
  {% if category.posts.size > 1 %}
     {{ cat }} 
     {% for p in category.posts %}
        {% if p.title != post.title %}
           {{ p.title }} - {{ p.description }}
        {% endif %}
  {% endif %}
{% endfor %}

Not tested.