2

I have a categories field on an entry that can have one or many children. I am able to output everything - but would like to restrict the field a bit more.

If a child has been selected, I do not want to show the parent. In my example, I only want to show "child".

It is possible, that I might only choose "parent" and I only want that to show. Or, is there a different way I should go about doing this? Thank you for any suggestions!

enter image description here

I've tried something like this:

{% for service in entry.servies %}
   {% set subCategories = craft.categories.descendantOf(service) %}

   {% if subCategories|length %}
       ...
   {% endif %}
{% endfor %}

But that will show the child category if it's selected or not. I would only like to show the "Child" category if it was actually selected. Otherwise, show the "parent" category.

UPDATE/SOLUTION

First, I want to thank Robin for your help. I tried different variations and was unsuccessful. I ended up taking my existing category and making it a structure. This gave me the flexibility that I needed.

2
  • I'm not sure if that works so it might be totally wrong (I can't test it now) but have you tried to order your entries by level and select the first? That way it might be possible to select only the deepest entry (child). Btw: if this is for Craft 3 keep in mind looping through queries is deprecated Commented Apr 24, 2018 at 22:09
  • Yes it's Craft 3. I have a category called "Service Types". On my entry, I have a category field called "Services". I'm trying to only show the category that was selected. I would like to not show the parent if the child was selected.
    – Damon
    Commented Apr 24, 2018 at 22:14

4 Answers 4

2

You can change the sort order in your CategoryQuery

{% set child = entry.getFieldValue('servies').orderBy('level DESC').one() %}

returns the category of the deepest level -> the child. If no child is selected you'll receive the parent

2
  • Hey Robin - thank you so much! I'm getting the child now like I'd like, but adding the one() will (obviously) only get me a single category. My entry could belong to several categories - some may have a child, some may not.
    – Damon
    Commented Apr 24, 2018 at 22:47
  • That's why I never understood Pixel and Tonic decision to make Category fields the way they are. The most easiest solution would be to create a custom field type.. Copy this github.com/craftcms/cms/blob/develop/src/fields/Entries.php and change the word Entry to Category and you are done after you registered your new field type. Only Category fields fill the gaps github.com/craftcms/cms/blob/develop/src/fields/… Commented Apr 24, 2018 at 22:53
1

Instead of a category, try creating each service within a structure. Then use an entries field to establish the relationship within the CP.

1

You can get the highest level of categories in your field and then filter your field only on that level.

{% set level = 0 %}
{% for productCategory in block.productCategories.all %}
    {% set level = productCategory.level > level ? productCategory.level : level %}
{% endfor %}

{% for productCategory in block.productCategories.level(level).all %}
    Do somestuff
{% endfor %}
1

You could loop through the selected categories, collect their ancestors and exclude them from the final entry query.

This syntax is wrong but something like:

{% set services = entry.services %}
{% set ancestors = [] %}

{% for service in services %}
  {% set ancestors = ancestors|merge(service.getAncestors()) %}
{% endfor %}

{% set mostSpecificServiceCategories = craft.categories(services).without(ancestors) %}

{% set entries = craft.entries.services(mostSpecificServiceCategories) %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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