Only show items related to the lowest category level I have a category group (CG).
I have a channel of entries with a matrix field (MF).
Every block in that matrix field has a category field linked to the CG.

I want to list all the MF blocks in an ordered list grouped by their category.
So for example:


Category A


MF block 1
MF block 2
Category AB


MF block 3




I'm looping over all categories within CG (with a recursive macro) and for each category I show a MF block that has that category related.
The problem is that when a block is related to Category AB, it is also related to its parent Category A, so the block is shown in Category A as well as in Category AB.

I want it to be only shown in the lowest level category, being AB in this case.

It gets even trickier because I cannot limit the amount of categories selected to just 1, because than Craft automatically selects only the top parent. So now (even if I don't need it) I have to take care of the possibility that the matrix block has multiple categories selected (and their children).

I was thinking about grouping the matrix blocks by their category with the groupBy filter plugin but I haven't found the time yet to try this out. And I'm afraid I might loose the hierarchy of the CG.

I could use a section for the categories (where you can limit it to a single item and it'll select the correct child) but than the client has a hard time to see what the parent category is in the CP. So that's a downer.

Why I need this: 

The client needs to be able to upload a ton of files related to an entry or add links related to an entry. That's why I created a matrix with 3 block types: external link, internal link and file.
The file block has a table field where they can upload an asset and select a locale. Because all files can have multiple translations. But the locales these files can be translated in do not match the locales that the site is available in. So that's why I can't just use a translatable asset field. That also why I can't use a front-end asset browser (because of the links and the translated files and because I have no control over the created folder structure).

I could live without them being able to add links if that would make it simpler. Alternative solutions are more than welcome!
This is a truly tricky one. Let's restate the problem:


  For each category in a tree list of categories: We want to display content from an element if the element is related to the category but not related to any of the category's children.


Off the top of my head, I can't think of a really performant way to do this... So, hopefully there aren't too many categories in your setup, and caching is key.

First we need to generate a recursive structure of categories:

{% set categories = craft.categories.group(...) %}

{% nav category in categories %}

    {% include '_elementsForThisCategory' with {category: category} only %}

    {% ifchildren %}
        {% children %}
    {% endifchildren %}

{% endnav %}


(You could easily use a macro in place of that include. These days I prefer includes over macros for anything other than the very simplest use cases.)

Next (in the included template/macro), we need to create a list of elements that are related to the present category but not related to any of its children:

{# Query entries that are related to this category's children. #}

{% set relatedToChildCats = craft.entries.relatedTo({
    targetElement: category.getChildren()
    field: 'yourMatrixField.yourCategoriesField'
}) %}

{# Query entries that are related to this category,
   and exclude the entries that are related to this category's children. #}

{% set theBuckStopsHere = craft.entries.relatedTo({
    targetElement: category
    field: 'yourMatrixField.yourCategoriesField'
}).id('not', relatedToChildCats.ids) %}

{# Display the content however you want. #}

{% for entry in theBuckStopsHere %}
    ...
{% endfor %}


&rarr; You probably noticed that my example uses Entry elements, and your stated use case deals with MatrixBlock elements. I wanted to give the example using purely out-of-the-box-friendly code, and unfortunately Craft 2 doesn't provide a template method for querying Matrix blocks... But luckily, our good friend Low wrote a nice plugin (Low Blocks), which adds a handy craft.lowBlocks template variable.