<p>I know this has been answered already, but here's my code for showing the children of the current parent:</p>

<pre><code>{% if entry.getParent(entry)|length %}
{% set subMenu = craft.entries.descendantOf(entry.getParent(entry)) %}

&lt;ul&gt;
    {% nav link in subMenu %}
    &lt;li&gt;&lt;a href="{{link.getUrl}}"&gt;{{link.title}}&lt;/a&gt;&lt;/li&gt;
    {% endnav %}
&lt;/ul&gt;

{% endif %}
</code></pre>

CC BY-SA 3.0
2014-09-06T14:56:26.260Z
2015-02-25T02:58:34.760Z
2015-02-25T02:58:34.760Z
darylknight
<p>This will do it:
</p>

<pre><code>{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry) %}

{% set numSegs = craft.request.segments|length %}
&lt;ul&gt;
{% nav page in subnav %}
  {% set thisOneIsActive = page.slug == craft.request.getSegment(page.level) %}
  {% set pageUrlSegs = (page.url|split('//'))[1]|split('/') %}
  {% set wantThisOne = thisOneIsActive or (pageUrlSegs|length &gt; numSegs and pageUrlSegs[numSegs] == craft.request.getLastSegment) %}
  {% if wantThisOne %}
    &lt;li{% if thisOneIsActive %} class="active"{% endif %}&gt;
      {{ page.getLink() }}
  {% endif %}
      {% ifchildren %}
        &lt;ul&gt;
          {% children %}
        &lt;/ul&gt;
      {% endifchildren %}
  {# at this point for whatever reason we have lost our context variables and have to recalculate them #}
  {% set thisOneIsActive = page.slug == craft.request.getSegment(page.level) %}
  {% set pageUrlSegs = (page.url|split('//'))[1]|split('/') %}
  {% set wantThisOne = thisOneIsActive or (pageUrlSegs|length &gt; numSegs and pageUrlSegs[numSegs] == craft.request.getLastSegment) %}
  {% if wantThisOne %}
    &lt;/li&gt;
  {% endif %}
{% endnav %}
&lt;/ul&gt;
</code></pre>

<p>I think it's kind of a hack. It works around the limitations of not being able to have the <code>ifchildren</code> in an <code>if</code> by calculating for every element whether or not we want to show it. And it works around the nav context no longer being set after the <code>ifchildren</code> block by making that calculation twice.</p>

<p>I think the <code>nav</code> tag has room for improvement (easier to say than to do, I know).</p>

CC BY-SA 3.0
2014-06-29T22:31:04.557Z
Thanks Marion! If that's the way to do it, I'd prefer the CSS workaround... Maybe the P&T guys can offer some insight. :)
Low
CC BY-SA 3.0
2014-06-29T23:44:45.793Z
I'd prefer the CSS workaround too. I think what we have here is a bug in the `nav` tag.
Marion Newlevant
CC BY-SA 3.0
2014-06-29T19:22:19.160Z
2014-06-29T19:22:19.160Z
Marion Newlevant
<p>I was working on a site where I needed dynamic sub nav similar to what I think you are describing - in order to solve the issue I set my arrays at the top of the page calculating by entry.level and page parent. I didn't do anything with active classes yet.</p>

<p>So if the nav tree is:</p>

<pre><code>About
--Leaders
--History
Groups
--Men
----Men Book Group
--Women
</code></pre>

<p>When you click on About you will be presented only with the sub nav "Leaders" and "History" and with my particular implementation it will display only the sub nav that belongs to a 2nd level nav item as well... so if you navigate to "Men" it will only show "Men Book Group" in the sidenav. I think you should be able to make it show that whole tree if you took of the if statement related to the 3rd level.</p>

<pre><code>{% if entry.level == '1' %}

    {% set pages = craft.entries.section('page').descendantOf( entry.id ).descendantDist(1) %}
    {% set parentLink = entry %}

{% elseif entry.level == '2' %}

    {% if entry.children.first == TRUE %}

        {% set pages = craft.entries.section('page').descendantOf( entry.id ) %}
        {% set parentLink = entry %}

    {% else %}

         {% set pages = craft.entries.section('page').descendantOf( entry.parent ) %}
         {% set parentLink = entry.parent %}

    {% endif %}

{% elseif entry.level == '3' %}

    {% set pages = craft.entries.section('page').descendantOf( entry.parent ) %}
    {% set parentLink = entry.parent %}

{% endif %}
</code></pre>

<p>My sub nav code is as follows:</p>

<pre><code>          &lt;ul&gt;&lt;li&gt;&lt;a href="{{ parentLink.url }}"&gt;{{ parentLink.title }}&lt;/a&gt;

            &lt;ul&gt;
            {% nav page in pages %}
                &lt;li&gt;
                    {% if page.type == 'link'  %}
                        {% set link = page.destination %}
                        &lt;a href="{{ link.url }}"&gt;{{ page.title }}&lt;/a&gt;
                    {% else %}
                        &lt;a href="{{ page.url }}"&gt;{{ page.title }}&lt;/a&gt;

                    {% endif %}

                    {% ifchildren %}
                        &lt;ul&gt;
                            {% children %}
                        &lt;/ul&gt;
                    {% endifchildren %}
                &lt;/li&gt;
            {% endnav %}
            &lt;/ul&gt;

            &lt;/li&gt;&lt;/ul&gt;
</code></pre>

<p>I hope this helps and I apologize if I have misunderstood the question!</p>

CC BY-SA 3.0
2014-06-30T20:16:22.140Z
You understood, but that approach won't work for an unknown amount of levels.
Low
CC BY-SA 3.0
2014-06-30T22:14:16.590Z
@Low Totally makes sense! I will try Ben's solution as well.
Alan Miller
CC BY-SA 3.0
2014-06-30T16:51:46.673Z
2014-06-30T16:51:46.673Z
Alan Miller
<p>You can now use the <a href="https://symfony.com/blog/twig-adds-filter-map-and-reduce-features#filter-map-and-reduce" rel="nofollow noreferrer">filter tag</a> of Twig.</p>
<p>So you can just do something like this:</p>
<pre><code>{% nav page in subnav|filter(page =&gt; page.slug == craft.request.getSegment(page.level) ) %}
    do some stuff
{% endnav %}
</code></pre>
<p>Another solution would be to print out the children only if the condition is true:</p>
<pre><code>  {% ifchildren %}
    {% if page.slug == craft.request.getSegment(page.level) %}
          &lt;ul&gt;
            {% children %}
          &lt;/ul&gt;
    {% endif %}
  {% endifchildren %}
</code></pre>
<p>Or combine them to get your wished result.</p>

CC BY-SA 4.0
2020-09-20T14:48:35.283Z
2020-09-20T14:48:35.283Z
Slowwie
<p>A recursive macro will help you get around the limitations of <code>ifchildren</code> (which P&amp;T will hopefully resolve soon), as follows:</p>

<pre class="lang-twig prettyprint-override"><code>{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry).level(2) %}

{% macro recursiveChildren(page) %}
  {% if page.hasDescendants and page.slug == craft.request.getSegment(page.level) %}
    &lt;ul&gt;
      {% for subpage in page.children %}
          &lt;li{% if subpage.slug == craft.request.getSegment(subpage.level) %} class="active"{% endif %}&gt;
            {{ subpage.link }}
            {{ _self.recursiveChildren(subpage) }}
          &lt;/li&gt;
      {% endfor %}
    &lt;/ul&gt;
  {% endif %}
{% endmacro %}

&lt;ul&gt;
{% for page in subnav %}
  &lt;li{% if page.slug == craft.request.getSegment(page.level) %} class="active"{% endif %}&gt;
    {{ page.link }}
    {{ _self.recursiveChildren(page) }}
  &lt;/li&gt;
{% endfor %}
&lt;/ul&gt;
</code></pre>

<p>More on <a href="http://twig.sensiolabs.org/doc/tags/macro.html">macros here</a>.</p>

CC BY-SA 3.0
2014-06-30T20:17:05.143Z
Yep, Best answer of the bunch so far. Thanks Ben.
Low
CC BY-SA 3.0
2014-07-01T08:11:52.047Z
Ben, I edited your example: the subnav should only contain level 2 pages to avoid duplicates, and I added the `if` statement to the macro to add `class="active"` to the list items.
Low
CC BY-SA 3.0
2014-07-01T11:07:13.053Z
great!! i suppose there are many tweaks that could be made to the code but the recursive macro is the key to the solution.
Ben Croker
CC BY-SA 3.0
2014-06-30T18:42:56.500Z
2014-07-01T11:05:15.813Z
2014-07-01T11:05:15.813Z
Ben Croker
<p>I've got a Structure section where the top level is the main menu. The submenu consists of the children of the active main menu item. This works well.</p>

<p>For the submenu, I'm using this code:</p>

<pre class="lang-twig prettyprint-override"><code>{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry) %}

&lt;ul&gt;
{% nav page in subnav %}
  &lt;li{% if page.slug == craft.request.getSegment(page.level) %} class="active"{% endif %}&gt;
    {{ page.getLink() }}
    {% ifchildren %}
      &lt;ul&gt;
        {% children %}
      &lt;/ul&gt;
    {% endifchildren %}
  &lt;/li&gt;
{% endnav %}
&lt;/ul&gt;
</code></pre>

<p>...which shows <em>all</em> children of each page.</p>

<p>How can I only show the children of the <em>active</em> parent? I've tried to wrap the <code>ifchildren</code> block inside another <code>if</code> statement (the same I used to set the <code>class="active"</code> to the <code>&lt;li&gt;</code>), but that results in a Template error:</p>

<blockquote>
  <p>Unexpected tag name "ifchildren" (expecting closing tag for the "if" tag defined near line <em>x</em>)</p>
</blockquote>

<p>Putting that <code>if</code> statement <em>inside</em> the <code>ifchildren</code> block also throws a template error.</p>

<p>PS. With the current HTML output, I could also just use CSS to hide/show the <code>&lt;ul&gt;</code>s based on the <code>.active</code> class, but I'd still like to know how to generate that tree without the need for  a CSS workaround.</p>

<structure><navigation>
How do you only show children of "active" parent in a Structure section's nav?
# How do you only show children of "active" parent in a Structure section's nav?

(Asked by: username_0 on 2014-06-29)

I've got a Structure section where the top level is the main menu. The submenu consists of the children of the active main menu item. This works well.
For the submenu, I'm using this code:
{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry) %}


{% nav page in subnav %}
  
    {{ page.getLink() }}
    {% ifchildren %}
      
        {% children %}
      
    {% endifchildren %}
  
{% endnav %}


...which shows all children of each page.
How can I only show the children of the active parent? I've tried to wrap the ifchildren block inside another if statement (the same I used to set the class="active" to the ), but that results in a Template error:

Unexpected tag name "ifchildren" (expecting closing tag for the "if" tag defined near line x)

Putting that if statement inside the ifchildren block also throws a template error.
PS. With the current HTML output, I could also just use CSS to hide/show the s based on the .active class, but I'd still like to know how to generate that tree without the need for  a CSS workaround.

**Tags:** structure, navigation


---

## 5 answers

### Answer by username_5 on 2014-06-30. Score: 17 | Accepted answer

A recursive macro will help you get around the limitations of ifchildren (which P&T will hopefully resolve soon), as follows:
{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry).level(2) %}

{% macro recursiveChildren(page) %}
  {% if page.hasDescendants and page.slug == craft.request.getSegment(page.level) %}
    
      {% for subpage in page.children %}
          
            {{ subpage.link }}
            {{ _self.recursiveChildren(subpage) }}
          
      {% endfor %}
    
  {% endif %}
{% endmacro %}


{% for page in subnav %}
  
    {{ page.link }}
    {{ _self.recursiveChildren(page) }}
  
{% endfor %}


More on macros here.

> **Comments:**
> **username_0**: Yep, Best answer of the bunch so far. Thanks Ben.  
> **username_0**: Ben, I edited your example: the subnav should only contain level 2 pages to avoid duplicates, and I added the `if` statement to the macro to add `class="active"` to the list items.  
> **username_5**: great!! i suppose there are many tweaks that could be made to the code but the recursive macro is the key to the solution.  

---

### Answer by username_1 on 2014-09-06. Score: 5

I know this has been answered already, but here's my code for showing the children of the current parent:
{% if entry.getParent(entry)|length %}
{% set subMenu = craft.entries.descendantOf(entry.getParent(entry)) %}


    {% nav link in subMenu %}
    {{link.title}}
    {% endnav %}


{% endif %}


---

### Answer by username_2 on 2014-06-29. Score: 4

This will do it:

{% set mainEntry = craft.entries.slug(craft.request.getSegment(1)).first() %}
{% set subnav = craft.entries.descendantOf(mainEntry) %}

{% set numSegs = craft.request.segments|length %}

{% nav page in subnav %}
  {% set thisOneIsActive = page.slug == craft.request.getSegment(page.level) %}
  {% set pageUrlSegs = (page.url|split('//'))[1]|split('/') %}
  {% set wantThisOne = thisOneIsActive or (pageUrlSegs|length > numSegs and pageUrlSegs[numSegs] == craft.request.getLastSegment) %}
  {% if wantThisOne %}
    
      {{ page.getLink() }}
  {% endif %}
      {% ifchildren %}
        
          {% children %}
        
      {% endifchildren %}
  {# at this point for whatever reason we have lost our context variables and have to recalculate them #}
  {% set thisOneIsActive = page.slug == craft.request.getSegment(page.level) %}
  {% set pageUrlSegs = (page.url|split('//'))[1]|split('/') %}
  {% set wantThisOne = thisOneIsActive or (pageUrlSegs|length > numSegs and pageUrlSegs[numSegs] == craft.request.getLastSegment) %}
  {% if wantThisOne %}
    
  {% endif %}
{% endnav %}


I think it's kind of a hack. It works around the limitations of not being able to have the ifchildren in an if by calculating for every element whether or not we want to show it. And it works around the nav context no longer being set after the ifchildren block by making that calculation twice.
I think the nav tag has room for improvement (easier to say than to do, I know).

> **Comments:**
> **username_0**: Thanks Marion! If that's the way to do it, I'd prefer the CSS workaround... Maybe the P&T guys can offer some insight. :)  
> **username_2**: I'd prefer the CSS workaround too. I think what we have here is a bug in the `nav` tag.  

---

### Answer by username_3 on 2014-06-30. Score: 3

I was working on a site where I needed dynamic sub nav similar to what I think you are describing - in order to solve the issue I set my arrays at the top of the page calculating by entry.level and page parent. I didn't do anything with active classes yet.
So if the nav tree is:
About
--Leaders
--History
Groups
--Men
----Men Book Group
--Women

When you click on About you will be presented only with the sub nav "Leaders" and "History" and with my particular implementation it will display only the sub nav that belongs to a 2nd level nav item as well... so if you navigate to "Men" it will only show "Men Book Group" in the sidenav. I think you should be able to make it show that whole tree if you took of the if statement related to the 3rd level.
{% if entry.level == '1' %}

    {% set pages = craft.entries.section('page').descendantOf( entry.id ).descendantDist(1) %}
    {% set parentLink = entry %}

{% elseif entry.level == '2' %}

    {% if entry.children.first == TRUE %}

        {% set pages = craft.entries.section('page').descendantOf( entry.id ) %}
        {% set parentLink = entry %}

    {% else %}

         {% set pages = craft.entries.section('page').descendantOf( entry.parent ) %}
         {% set parentLink = entry.parent %}

    {% endif %}

{% elseif entry.level == '3' %}

    {% set pages = craft.entries.section('page').descendantOf( entry.parent ) %}
    {% set parentLink = entry.parent %}

{% endif %}

My sub nav code is as follows:
          {{ parentLink.title }}

            
            {% nav page in pages %}
                
                    {% if page.type == 'link'  %}
                        {% set link = page.destination %}
                        {{ page.title }}
                    {% else %}
                        {{ page.title }}

                    {% endif %}

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

            

I hope this helps and I apologize if I have misunderstood the question!

> **Comments:**
> **username_0**: You understood, but that approach won't work for an unknown amount of levels.  
> **username_3**: @username_0 Totally makes sense! I will try Ben's solution as well.  

---

### Answer by username_4 on 2020-09-20. Score: 1

You can now use the filter tag of Twig.
So you can just do something like this:
{% nav page in subnav|filter(page => page.slug == craft.request.getSegment(page.level) ) %}
    do some stuff
{% endnav %}

Another solution would be to print out the children only if the condition is true:
  {% ifchildren %}
    {% if page.slug == craft.request.getSegment(page.level) %}
          
            {% children %}
          
    {% endif %}
  {% endifchildren %}

Or combine them to get your wished result.


---

