<p>The <code>descendants</code> of an element include anything nested within it, regardless of depth.</p>
<p>I believe what you want is <code>children</code>:</p>
<pre><code>{% set topLevelComments = craft.entries()
  .section('articleComments')
  .relatedTo(entry)
  .level(1) %}

{% macro renderComments(comments) %}
  &lt;ul&gt;
    {% for comment in comments %}
      &lt;li&gt;
        &lt;p&gt;{{ comment.comment }}&lt;/p&gt;

        {% set children = comment.children.eagerly().all() %}

        {% if children is not empty %}
          {{ _self.renderComments(children) }}
        {% endif %}
      &lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endmacro %}

{% import _self as comments %}

{{ comments.renderComments(topLevelComments) }}
</code></pre>
<p>There is no need to manually define an eager-loading map—this revised example uses Craft 5’s <a href="https://craftcms.com/docs/5.x/development/eager-loading.html#lazy-eager-loading" rel="nofollow noreferrer">lazy eager-loading</a> feature. (In previous versions, you may need to call <code>.with([['children.children.children']])</code> for as many levels you expect comments to be nested!)</p>
<h3>Bonus</h3>
<p>If you were to display a form to add replies, you can test whether it exceeds the section’s &quot;Maximum Levels&quot; setting:</p>
<pre><code>{% set section = comment.section %}

{% if comment.level &lt; section.maxLevels %}
  &lt;form&gt;
    {# ... #}
  &lt;/form&gt;
{% endif %}
</code></pre>

CC BY-SA 4.0
2024-06-04T20:43:44.153Z
Thank you! of course, that was the reason. One more question. I got an error that the eagerly method does not exist. Do you know why? As far as I can see in the docs, this should work?
smaniren
CC BY-SA 4.0
2024-06-06T17:55:32.523Z
Without seeing the entire template in its final state, I can't say for sure. This was added in Craft 5, which the title suggests you're using… but the method doesn't exist on “element collections,” which can be returned by `comment.children`.

Worth trying the `children.children.children` eager-loading map (and removing `.eagerly()` temporarily) to make sure the change from `descendants` works in isolation!
August Miller
CC BY-SA 4.0
2024-06-04T20:09:40.857Z
2024-06-04T20:09:40.857Z
August Miller
<p>I'm trying to display my nested comments. I've created 7 test-comments:</p>
<pre><code>ID   Parent ID   Comment    Descendants Count   Level
785  N/A         test 1     6                   1
788  785         test 2     5                   2
791  788         test 3     4                   3
794  791         test 4     3                   4
797  794         test 5     2                   5
800  797         test 6     1                   6
803  800         test 7     0                   7
</code></pre>
<p>As you can see &quot;test 1&quot; is parent of &quot;test 2&quot;, &quot;test 2&quot; is parent of &quot;test 3&quot; and so on.</p>
<p>My goal is to display the Comments like this:</p>
<pre><code>|test 1
  |-test 2
    |-test 3
      |-test 4
        |-test 5
          |-test 6
            |-test 7
</code></pre>
<p>but what i get is this:</p>
<pre><code>|test 1
  |-test 2
    |-test 3
    | |-test 4
    | | |-test 5
    | | | |-test 6
    | | | | |-test 7
    | | | | |-test 7
    | | | |-test 6
    | | |   |-test 7
    | | |   |-test 7
    | | |-test 5
    | |   |-test 6
    | |   | |-test 7
    | |   | |-test 7
    | |   |-test 6
    | |     |-test 7
    | |     |-test 7
    | |-test 4
    |   |-test 5
    |     |-test 6
    |     | |-test 7
    |     | |-test 7
    |     |-test 6
    |       |-test 7
    |       |-test 7
    |   |-test 5
    |     |-test 6
    |     | |-test 7
    |     | |-test 7
    |     |-test 6
    |       |-test 7
    |       |-test 7
    |-test 3
      |-test 4
      | |-test 5
      | | |-test 6
      | | | |-test 7
      | | | |-test 7
      | | |-test 6
      | |   |-test 7
      | |   |-test 7
      | |-test 5
      |   |-test 6
      |   | |-test 7
      |   | |-test 7
      |   |-test 6
      |     |-test 7
      |     |-test 7
      |-test 4
        |-test 5
        | |-test 6
        | | |-test 7
        | | |-test 7
        | |-test 6
        |   |-test 7
        |   |-test 7
        |-test 5
          |-test 6
          | |-test 7
          | |-test 7
          |-test 6
            |-test 7
            |-test 7
</code></pre>
<p>As you can see, the macro works for the first 2 levels. but after that it somehow repeats some levels.</p>
<p>Here is my code:</p>
<pre><code>{# select only the top comments --&gt; only id 785 in this case #}
{% set topLevelComments = craft.entries()
    .section('articleComments')
    .relatedTo(entry)
    .with(['descendants'])
    .level(1) %}


{# Define a macro to render comments recursively #}
{% macro renderComments(comments) %}
    &lt;ul&gt;
        {% for comment in comments %}
        {% set level = (comment.level - 1) * 20 %}
            &lt;li&gt;
                &lt;div style=&quot;margin-left:{{level}}px&quot; class=&quot;border flex gap-3&quot;&gt;
                    &lt;p&gt;{{ comment.comment }}&lt;/p&gt;
                &lt;/div&gt;

                {% if comment.getHasDescendants()%}
                    {{ _self.renderComments(comment.getDescendants().all()) }}
                {% endif %}

            &lt;/li&gt;
        {% endfor %}
    &lt;/ul&gt;
{% endmacro %}

{% import _self as comments %}
{{ comments.renderComments(topLevelComments) }}

</code></pre>
<p>has anyone an idea where i did something wrong?</p>

<macro><craft5><nested>
Problem with recursive macro descendants in craft 5
# Problem with recursive macro descendants in craft 5

(Asked by: username_0 on 2024-06-04)

I'm trying to display my nested comments. I've created 7 test-comments:
ID   Parent ID   Comment    Descendants Count   Level
785  N/A         test 1     6                   1
788  785         test 2     5                   2
791  788         test 3     4                   3
794  791         test 4     3                   4
797  794         test 5     2                   5
800  797         test 6     1                   6
803  800         test 7     0                   7

As you can see "test 1" is parent of "test 2", "test 2" is parent of "test 3" and so on.
My goal is to display the Comments like this:
|test 1
  |-test 2
    |-test 3
      |-test 4
        |-test 5
          |-test 6
            |-test 7

but what i get is this:
|test 1
  |-test 2
    |-test 3
    | |-test 4
    | | |-test 5
    | | | |-test 6
    | | | | |-test 7
    | | | | |-test 7
    | | | |-test 6
    | | |   |-test 7
    | | |   |-test 7
    | | |-test 5
    | |   |-test 6
    | |   | |-test 7
    | |   | |-test 7
    | |   |-test 6
    | |     |-test 7
    | |     |-test 7
    | |-test 4
    |   |-test 5
    |     |-test 6
    |     | |-test 7
    |     | |-test 7
    |     |-test 6
    |       |-test 7
    |       |-test 7
    |   |-test 5
    |     |-test 6
    |     | |-test 7
    |     | |-test 7
    |     |-test 6
    |       |-test 7
    |       |-test 7
    |-test 3
      |-test 4
      | |-test 5
      | | |-test 6
      | | | |-test 7
      | | | |-test 7
      | | |-test 6
      | |   |-test 7
      | |   |-test 7
      | |-test 5
      |   |-test 6
      |   | |-test 7
      |   | |-test 7
      |   |-test 6
      |     |-test 7
      |     |-test 7
      |-test 4
        |-test 5
        | |-test 6
        | | |-test 7
        | | |-test 7
        | |-test 6
        |   |-test 7
        |   |-test 7
        |-test 5
          |-test 6
          | |-test 7
          | |-test 7
          |-test 6
            |-test 7
            |-test 7

As you can see, the macro works for the first 2 levels. but after that it somehow repeats some levels.
Here is my code:
{# select only the top comments --> only id 785 in this case #}
{% set topLevelComments = craft.entries()
    .section('articleComments')
    .relatedTo(entry)
    .with(['descendants'])
    .level(1) %}


{# Define a macro to render comments recursively #}
{% macro renderComments(comments) %}
    
        {% for comment in comments %}
        {% set level = (comment.level - 1) * 20 %}
            
                
                    {{ comment.comment }}
                

                {% if comment.getHasDescendants()%}
                    {{ _self.renderComments(comment.getDescendants().all()) }}
                {% endif %}

            
        {% endfor %}
    
{% endmacro %}

{% import _self as comments %}
{{ comments.renderComments(topLevelComments) }}


has anyone an idea where i did something wrong?

**Tags:** macro, craft5, nested

---

## 1 answers

### Answer by username_1 on 2024-06-04. Score: 1 | Accepted answer

The descendants of an element include anything nested within it, regardless of depth.
I believe what you want is children:
{% set topLevelComments = craft.entries()
  .section('articleComments')
  .relatedTo(entry)
  .level(1) %}

{% macro renderComments(comments) %}
  
    {% for comment in comments %}
      
        {{ comment.comment }}

        {% set children = comment.children.eagerly().all() %}

        {% if children is not empty %}
          {{ _self.renderComments(children) }}
        {% endif %}
      
    {% endfor %}
  
{% endmacro %}

{% import _self as comments %}

{{ comments.renderComments(topLevelComments) }}

There is no need to manually define an eager-loading map—this revised example uses Craft 5’s lazy eager-loading feature. (In previous versions, you may need to call .with([['children.children.children']]) for as many levels you expect comments to be nested!)
Bonus
If you were to display a form to add replies, you can test whether it exceeds the section’s "Maximum Levels" setting:
{% set section = comment.section %}

{% if comment.level < section.maxLevels %}
  
    {# ... #}
  
{% endif %}

> **Comments:**
> **username_0**: Thank you! of course, that was the reason. One more question. I got an error that the eagerly method does not exist. Do you know why? As far as I can see in the docs, this should work?  
> **username_1**: Without seeing the entire template in its final state, I can't say for sure. This was added in Craft 5, which the title suggests you're using… but the method doesn't exist on “element collections,” which can be returned by `comment.children`.  Worth trying the `children.children.children` eager-loading map (and removing `.eagerly()` temporarily) to make sure the change from `descendants` works in isolation!  

---

