In my list.htm (where the above template is rendered): I have the following:
<ul class="post-list">
{% for post in posts %}
{# <!-- reset for each post --> #}
{% set otherCats = allCategories %}
<li class="mb_2 pb_1">
<h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p class="info greyed">
Posted
{% if post.categories|length %} in {% endif %}
{% for category in post.categories %}
<a href="{{ category.url }}">{{ category.name }}</a>
<!-- working fine -->
{% if not loop.last %}, {% endif %}
{% set otherCats = otherCats | filter((v,k) => v.id != category.id ) %}
{% endfor %}
on {{ post.published_at|date('M d, Y') }}.
<span class="small-text">
(more posts in
{% for otherCat in otherCats %}
<a href="{{ 'blog/category' | page({'slug': otherCat.slug}) }}">{{ otherCat.name }}</a>
<!-- not working! -->
{% if not loop.last %}, {% endif %}
{% endfor %})
</span>
</p>
The second for loop (“for otherCat in otherCats”), is correctly rendering the remaining other categories (not belonging to the current post in the loop), however, the ", " is still being added even though it should not, as shown here:
Very strange behaviour, perhaps I have missed something with the array? I looked but it doesn’t seem like there’s an array clone feature for twig (?)
Main problem of this loop is, that you “replaces” array, then first iterator of loop contains items from allCategories. just simply rename that second array as {% set filteredCats = ... %} and make loop on this.
OK I got it working the long way (lots of for loops lol - see below), but I think @Eoler is correct with the issue solved in twig 4 as logically I can’t see anything wrong with the filtering code (I think issue is it returns a filterIterable thing instead of an actual array)
{% set posts = __SELF__.posts %}
{#<!-- overrides both default.htm (blog home) and category.htm, to render list of posts -->#}
<ul class="post-list">
{% for post in posts %}
{# <!-- reset for each post --> #}
{#{% set otherCats = allCategories %}#}
<li class="mb_2 pb_1">
<h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
<p class="info greyed">
Posted
{% if post.categories|length %} in {% endif %}
{% for category in post.categories %}
<a href="{{ category.url }}">{{ category.name }}</a>{% if not loop.last %}, {% endif %}
{# Doesn't work, see#}
{# https://talk.octobercms.com/t/twig-if-not-loop-last-not-working-for-second-loop-but-is-for-first/3031/3#}
{#{% set otherCats = otherCats | filter((v,k) => v.id != category.id ) %}#}
{% endfor %}
on {{ post.published_at|date('M d, Y') }}.
{# Find the other categories, the long way :) #}
{% set otherCats = [] %}
{% for cat in allCategories %}
{% set found = false %}
{# Note: if (cat not in post.categories) doesn't work #}
{% for postCat in post.categories %}
{% if cat.id == postCat.id %}
{% set found = true %}
{% endif %}
{% endfor %}
{% if found == false %}
{% set otherCats = otherCats|merge([cat]) %}
{% endif %}
{% endfor %}
<span class="small-text">
(more posts in
{% for otherCat in otherCats %}
<a href="{{ 'blog/category' | page({'slug': otherCat.slug}) }}">{{ otherCat.name }}</a>{% if not loop.last %}, {% endif %}{% endfor %})
</span>
</p>
<p class="excerpt">{{ post.summary|raw }}</p>
{% if post.featured_images|length %}
<div class="featured-images text-center">
{% for image in post.featured_images %}
<p>
<a href="{{ post.url }}">
<img
data-src="{{ image.filename }}"
src="{{ image.path }}"
alt="{{ image.description }}"
style="max-width: 30%" />
</a>
</p>
{% endfor %}
</div>
{% endif %}
<a class="" href="{{ post.url }}">Read more ...</a>
</li>
{% else %}
<li class="no-data">{{ __SELF__.noPostsMessage }}</li>
{% endfor %}
</ul>
{% if posts.lastPage > 1 %}
<ul class="pagination">
{% if posts.currentPage > 1 %}
<li><a href="{{ this.page.baseFileName|page({ (__SELF__.pageParam): (posts.currentPage-1) }) }}">← Prev</a></li>
{% endif %}
{% for page in 1..posts.lastPage %}
<li class="{{ posts.currentPage == page ? 'active' : null }}">
<a href="{{ this.page.baseFileName|page({ (__SELF__.pageParam): page }) }}">{{ page }}</a>
</li>
{% endfor %}
{% if posts.lastPage > posts.currentPage %}
<li><a href="{{ this.page.baseFileName|page({ (__SELF__.pageParam): (posts.currentPage+1) }) }}">Next →</a></li>
{% endif %}
</ul>
{% endif %}