<p>I would probably do this using the <code>group</code> filter, perhaps something like this:</p>
<pre><code>{% set itemsGrouped = entry.fieldname.all()|group(item =&gt; item.parent().title) %}
{% for parentTitle, items in itemsGrouped %}
    &lt;h3&gt;{{ parentTitle }}&lt;/h3&gt;
    {% if items|length %}
       &lt;ul&gt;
           {% for item in items %}
               &lt;li&gt;&lt;a href=&quot;{{ item.url }}&quot;&gt;{{ item.title }}&lt;/a&gt;&lt;/li&gt;
           {% endfor %}
       &lt;/ul&gt;
    {% endif %}
{% endfor %}
</code></pre>
<p>You may need to add some additional logic for dealing with cases where there is no parent.</p>

CC BY-SA 4.0
2022-01-22T15:01:22.857Z
Thank you James! This solution works if I change the code just a bit:
{% set itemsGrouped = entry.fieldname.all()|group(item => item.parent()) %}

instead of 

{% set itemsGrouped = entry.fieldname.all()|group(item => item.parent().title) %}
Marcel
CC BY-SA 4.0
2022-01-23T09:48:51.103Z
'item.parent.title' works as well
Marcel
CC BY-SA 4.0
2022-01-24T09:59:08.610Z
These are interesting points you raised: 1) `group(item => item.parent().title)` fails on items that don't have a parent. Working around this with `group(item => item.parent())` works in that it silences the error and automatically defaults to the title, but it's a bit magical for my liking. I'd prefer `group(item => item.parent().title ?? null)` continued...
James Smith
CC BY-SA 4.0
2022-01-24T10:02:48.543Z
...2) Passing a string to the `group` filter instead of an arrow function - `group('parent.title')` - will work too, however I've found that method can get extremely inefficient in more complex templates, because it instantiates the template parser for every item in the array, which in turn results in an N+1 problem that can add thousands of extra DB queries: https://github.com/craftcms/cms/blob/develop/src/web/twig/Extension.php#L1068 - for this reason it's best to always pass an arrow function to `group`.
James Smith
CC BY-SA 4.0
2022-01-26T10:58:05.863Z
Hi James, thank you for looking at it so thoroughly, because I did indeed run into a new problem.  That has now been solved by your first suggestion. Very nice to be assisted by real professionals!
Marcel
CC BY-SA 4.0
2022-01-21T16:45:39.100Z
2022-01-21T16:45:39.100Z
James Smith
<p>There's actually a service method that does exactly this, filling in ancestors in an array of elements. See <a href="https://docs.craftcms.com/api/v3/craft-services-structures.html#method-fillgapsinelements" rel="nofollow noreferrer"><code>Structures::fillGapsInElements</code></a>. This method will add the parent page as the first item in the array, so once you have this you can use one for-loop, opening and closing nested lists depending on the level (or use the <a href="https://craftcms.com/docs/3.x/dev/tags.html#nav" rel="nofollow noreferrer"><code>nav</code> tag</a> to do this).</p>
<p>Unfortunately, you can't use this method in directly in Twig. It takes an array parameter by reference and modifies it directly, which doesn't work with the way variables are accessed in a Twig context. You can create a simple <a href="https://craftcms.com/docs/3.x/extend/extending-twig.html" rel="nofollow noreferrer">Twig extension</a> with a method that just calls the method above and returns the result. Then you can call this method from Twig.</p>
<hr />
<p>Another option would be to use categories for your reference field, if the data structure permits this. Category fields enforce this behaviour by default: Ancestors of selected categories are automatically selected as well.</p>

CC BY-SA 4.0
2022-01-21T14:51:59.047Z
Thank you very much MoritzLost, for this clear answer!
Marcel
CC BY-SA 4.0
2022-01-21T15:04:26.620Z
@Marcel If the solution works for you, don't forget to mark the answer as accepted :)
MoritzLost
CC BY-SA 4.0
2022-01-21T14:46:31.020Z
2022-01-21T14:46:31.020Z
MoritzLost
<p>I have entries where other entries from a structure can be selected as related entries. The structure is one level deep.
If sublevel 1.1 and sublevel 1.3 are selected as related entries, I want to show it on a webpage in the context of the toplevel:</p>
<pre><code>Toplevel 1
- sublevel 1.1
- sublevel 1.3
</code></pre>
<p>I tried to do it like this:</p>
<pre><code>{% set items = entry.fieldname.all() %}
{% for item in items %}
    {% if item.getParent() %}
    {% set parent = item.getParent() %}
      &lt;li&gt;&lt;a href=&quot;{{ parent.url }}&quot;&gt;{{ parent.title }}&lt;/a&gt;&lt;/li&gt;
          &lt;ul class=&quot;inner-related&quot;&gt;
              &lt;li&gt;&lt;a href={{ item.slug }}&quot;&gt;{{ item.title }}&lt;/a&gt;&lt;/li&gt;
          &lt;/ul&gt;
    {% endif %}
{% endfor %}
</code></pre>
<p>But this will show up as:</p>
<pre><code>Toplevel 1
- sublevel 1.1

Toplevel 1
- sublevel 1.3
</code></pre>
<p>Is there a way to do it right?</p>

<structure>
Show 'active' related entries from a structure under one parent
# Show 'active' related entries from a structure under one parent

(Asked by: username_0 on 2022-01-21)

I have entries where other entries from a structure can be selected as related entries. The structure is one level deep.
If sublevel 1.1 and sublevel 1.3 are selected as related entries, I want to show it on a webpage in the context of the toplevel:
Toplevel 1
- sublevel 1.1
- sublevel 1.3

I tried to do it like this:
{% set items = entry.fieldname.all() %}
{% for item in items %}
    {% if item.getParent() %}
    {% set parent = item.getParent() %}
      {{ parent.title }}
          
              {{ item.title }}
          
    {% endif %}
{% endfor %}

But this will show up as:
Toplevel 1
- sublevel 1.1

Toplevel 1
- sublevel 1.3

Is there a way to do it right?

**Tags:** structure


---

## 2 answers

### Answer by username_1 on 2022-01-21. Score: 2 | Accepted answer

I would probably do this using the group filter, perhaps something like this:
{% set itemsGrouped = entry.fieldname.all()|group(item => item.parent().title) %}
{% for parentTitle, items in itemsGrouped %}
    {{ parentTitle }}
    {% if items|length %}
       
           {% for item in items %}
               {{ item.title }}
           {% endfor %}
       
    {% endif %}
{% endfor %}

You may need to add some additional logic for dealing with cases where there is no parent.

> **Comments:**
> **username_0**: Thank you James! This solution works if I change the code just a bit: {% set itemsGrouped = entry.fieldname.all()|group(item => item.parent()) %}  instead of   {% set itemsGrouped = entry.fieldname.all()|group(item => item.parent().title) %}  
> **username_0**: 'item.parent.title' works as well  
> **username_1**: These are interesting points you raised: 1) `group(item => item.parent().title)` fails on items that don't have a parent. Working around this with `group(item => item.parent())` works in that it silences the error and automatically defaults to the title, but it's a bit magical for my liking. I'd prefer `group(item => item.parent().title ?? null)` continued...  
> **username_1**: ...2) Passing a string to the `group` filter instead of an arrow function - `group('parent.title')` - will work too, however I've found that method can get extremely inefficient in more complex templates, because it instantiates the template parser for every item in the array, which in turn results in an N+1 problem that can add thousands of extra DB queries: https://github.com/craftcms/cms/blob/develop/src/web/twig/Extension.php#L1068 - for this reason it's best to always pass an arrow function to `group`.  
> **username_0**: Hi James, thank you for looking at it so thoroughly, because I did indeed run into a new problem.  That has now been solved by your first suggestion. Very nice to be assisted by real professionals!  

---

### Answer by username_2 on 2022-01-21. Score: 1

There's actually a service method that does exactly this, filling in ancestors in an array of elements. See [`Structures::fillGapsInElements`](https://docs.craftcms.com/api/v3/craft-services-structures.html#method-fillgapsinelements). This method will add the parent page as the first item in the array, so once you have this you can use one for-loop, opening and closing nested lists depending on the level (or use the [`nav` tag](https://craftcms.com/docs/3.x/dev/tags.html#nav) to do this).

Unfortunately, you can't use this method in directly in Twig. It takes an array parameter by reference and modifies it directly, which doesn't work with the way variables are accessed in a Twig context. You can create a simple [Twig extension](https://craftcms.com/docs/3.x/extend/extending-twig.html) with a method that just calls the method above and returns the result. Then you can call this method from Twig.

---

Another option would be to use categories for your reference field, if the data structure permits this. Category fields enforce this behaviour by default: Ancestors of selected categories are automatically selected as well.

> **Comments:**
> **username_0**: Thank you very much username_2, for this clear answer!  
> **username_2**: @username_0 If the solution works for you, don't forget to mark the answer as accepted :)  

---

