2

I am going to try this again...

I have a page for a category (country) with all the entries that match that country.

I have buttons that allow you to filter the entries using categories from a second category group ('market').

All, I want to do is list the markets to make the filter buttons.
BUT, I don't want to list the parent if their is a child. And, there is not always a child.

enter image description here

This is how I have things setup.

{% set entries = craft.entries.relatedTo(category).find() %}
{% set markets = craft.categories.group('markets').relatedTo(entries).find() %}

But, this prints both the parent and child of a market. I don't want to print the parent if there is a child.

Addling level(x) does not work because then it leaves out those markets that might be x+1 or x-1.

And adding last() did not work.

This has to be possible. It's killing me.

3

You could just use what you got, loop through the categories and try to grab the descendants for each of them.

{% set entries = craft.entries.relatedTo(category) %}
{% set allMarkets = craft.categories.group('markets').level(1).relatedTo(entries) %}

{% for market in allMarkets %}
    {% set descMarkets = market.getDescendants() %}

    {% if descMarkets %}
        {% for market in descMarkets %}
            {% include '_includes/partial' %}
        {% endfor %}
    {% else %}
        {% include '_includes/partial' %}
    {% endif %}
{% endfor %}

Another good approach is to "collect" element IDs.

You would basically do the same as in the output loop of the above example, but instead of having the conditionals and extra queries in the output loop, you’d work with element IDs that you merge into an array. You can then query for the categories nicely using the id param in a craft.categories criteria model.

{% set entries = craft.entries.relatedTo(category) %}
{% set topMarkets = craft.categories.group('markets').level(1).relatedTo(entries) %}

{% set allMarketIds = [] %}

{% for market in topMarkets %}
    {% set descMarketIds = craft.categories.descendantOf(market).ids() %}

    {% if descMarketIds %}
        {% set allMarketIds = allMarketIds|merge(descMarketIds) %}
    {% else %}
        {% set allMarketIds = allMarketIds|merge([market.id]) %}
    {% endif %}
{% endfor %}

{% set allMarkets = craft.categories.id(allMarketIds) %}

{% for market in allMarkets %}
    {% include '_includes/partial' %}
{% endfor %}

Update:

One more approach! I just noticed, that you can simply test whether a category has descendants or not. This should probably be best from a performance point of view.

{% set entries = craft.entries.relatedTo(category) %}
{% set allMarkets = craft.categories.group('markets').relatedTo(entries) %}

{% for market in allMarkets %}
    {% if market.getDescendants().total() == 0 %}
        {% include '_includes/partial' %}
    {% endif %}
{% endfor %}
  • I got both to work. I assume the second approach is more efficient - and potentially a best practice? – Hellyar Mar 9 '17 at 11:20
  • @Hellyar yeah, I like the idea of separating the data fetching and preparation from the actual output as much as possible (approach 2). But I just updated the answer with a new idea. Should be the most efficient and I would probably go with that because of that very reason. – carlcs Mar 9 '17 at 12:54
  • That's clean. But, I am going to try and see if I can apply the array approach elsewhere on the site I'm building. Thanks. – Hellyar Mar 9 '17 at 18:12
  • 1
    It’s also possible to just check if entry.hasDescendants is false. This feels a bit cleaner, although it doesn’t seem to save any queries, as I’d hoped it might. – Dom Stubbs Dec 19 '17 at 13:19

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.