Looping through a category group to show links to all the categories. This is an entry page and I want to highlight any categories assigned to the entry. How do I do that? I've tried this so far:

{% set cats = craft.categories.group('events').find() %}
{% for cat in cats %}
    <a href="{{ cat.url }}" {% if cat.relatedTo(entry) %}class=active{% endif %}>{{ cat.title }}</a>
{% endfor %}

Your solution looks like it's almost there, but it would be making a lot of DB queries as Craft will be querying the database for each category. You can give Craft all the help you can with something like this.

{# First, retrieve all of your events categories #}
{% set cats = craft.categories.group('events').find() %}

{# Get the IDs of all categories related to this entry #}
{% set relatedCats = craft.categories.group('events').relatedTo({sourceElement: entry}).ids() %}

{# Test if the current category ID is in the array of related category IDs #}
{% for cat in cats %}
    <a href="{{ cat.url }}" {% if cat.id in relatedCats %}class="active"{% endif %}>{{ cat.title }}</a>
{% endfor %}
  • Brilliant. Works a treat. I know cat.relatedTo(entry) wasn't working, but, if it was, why would that have meant more DB queries? Is it because entry.relatedTo(cat) would query the DB each time? Jun 19 '14 at 10:40
  • Yeah, exactly Clive. Relations between element types (like entries and categories) are stored in a DB table. When you call .relatedTo(), Craft has to build a query to search this. Because you're calling .relatedTo() within a loop, the database will be queried for every category you iterate over, and the queries can be quite big. Jun 19 '14 at 10:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.