1

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) %}
    <ul>
        {% for comment in comments %}
        {% set level = (comment.level - 1) * 20 %}
            <li>
                <div style="margin-left:{{level}}px" class="border flex gap-3">
                    <p>{{ comment.comment }}</p>
                </div>

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

            </li>
        {% endfor %}
    </ul>
{% endmacro %}

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

has anyone an idea where i did something wrong?

1 Answer 1

1

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) %}
  <ul>
    {% for comment in comments %}
      <li>
        <p>{{ comment.comment }}</p>

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

        {% if children is not empty %}
          {{ _self.renderComments(children) }}
        {% endif %}
      </li>
    {% endfor %}
  </ul>
{% 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 %}
  <form>
    {# ... #}
  </form>
{% endif %}
2
  • 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
    Commented Jun 4 at 20:43
  • 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! Commented Jun 6 at 17:55

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.