Menu System only for 2nd and 3rd level

Hi everybody,

I’m trying to setup a Menu which show only the 2nd and the 3rd Level of the Main Menu. Anybody a idea how to manage this? I have tried with Tree Menu and a few other snippets but can’t get it to work!

Any help would be great :slight_smile:

Show us the code you already got and the result you’re trying to achieve. That way we can help you get there :slight_smile:

You are referring to this Tree menu?

The tree menu is recursive from the starting point you give it, so it should work. But as @dreadnip says, please show the code you have tried.

I am guessing you are trying to setup a sidebar menu that only shows pages in the currently viewed section?

@jimbobrjames, exactly :grinning:

I was using the Treemenu but problem is that this also shows the 1st Level which is not needed. Also general the Treemenu has a Bug, there a Function for the “active” Class, but the active class is only applied to the direct item and not the parents … so a little bit useless for most cases.

You’ll need to give us more specific information on what your end goal is. How many pages do you have? Do you want to only display second level pages, or a mix of some first and second level? Either type out your folder/page structure or provide a screenshot and explain what the final menu should look like.

To get all second level pages, you can do this:

$secondLevel = $site->index()->filterby('depth', '==', 2);

Then you can check for each page if it has children or not.

As regards the active class, it’s not a bug, it depends on your use case, There are two methods, isActive() and isOpen(). See the docs for the difference.

Sorry for the less informations. I will try to explan it better. Let’s say my page has the following structure:

• Home
• Service
--- Service 1
--- Service 2
--- Service 3
------ Service 3.1
------ Service 3.2
------ Service 3.3
• Blog
--- Blog Entry 1
--- Blog Entry 2
--- Blog Entry 3
• Contact

So, when I now click on “Service”, I would like that in the Sidebar Menu there should be “Service 1, 2, 3”. But when I click on “Service 3”, “Service 1, 2, 3” should also stay and additional the “Service 3.1, 3.2, 3.3”.

That’s really hard to explain :grinning: it should be a Submenu of the Active Page. I have also tried with $page->children but without success cause then only the Children are show, and not the grandchildren. For example in Joomla CMS I would config the Menu that Level 2 of the Base is the Start Point for the Menu.

Here’s the “default” Tree Menu which also Lists "Home, Service, Blog … " every time.

<?php if(!isset($subpages)) $subpages = $site->children() ?>
<ul>
  <?php foreach($subpages->visible() AS $subpage): ?>
  <li class="depth-<?= $subpage->depth() ?> <?php e($subpage->isOpen(), ' active') ?>">
    <a href="<?= $subpage->url() ?>"><?= $subpage->title()->html() ?></a>
    <?php if($subpage->hasChildren()): ?>
    <?php snippet('sidebar-default', array('subpages' => $subpage->children())) ?>
    <?php endif ?>
  </li>
  <?php endforeach ?>
</ul>

And thanks @texnixe for the hint with isActive and isOpen

By the way, I’m searching for exactly this menu, but I have checked Github and seen that Bastian checks before that it’s children of docs. But I’m looking for a more “general” function.

https://getkirby.com/docs/installation/on-a-mac

https://getkirby.com/docs/cookbook/menus#sub-menu

Yes, I know this also. But was not able to connect it with the next level :frowning:

Something like this:

<?php

$items = false;

// get the open item on the first level
if($root = $pages->findOpen()) {

  // get visible children for the root item
  $items = $root->children()->visible();
}

// only show the menu if items are available
if($items and $items->count()):

?>
<nav>
  <ul>
    <?php foreach($items as $item): ?>
    <li><a<?php e($item->isOpen(), ' class="active"') ?> href="<?= $item->url() ?>"><?= $item->title()->html() ?></a></li>
     <?php if($item->hasChildren(): ?>
       <ul>
       <?php foreach($item->children() as $child): ?>
        <li><a<?php e($item->isActive(), ' class="active"') ?> href="<?= $child->url() ?>"><?= $child->title()->html() ?></a></li>
       <?php endforeach ?>
       </ul>
       <?php endif ?>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>

Add classes as required.

1 Like

That was the missing Part!! Thanks so much @texnixe! There are a few Errors in the above Code, missing endif and some small others. For all others which searching for this, use:

<?php

$items = false;

if($root = $pages->findOpen()) {
  $items = $root->children()->visible();
}

if($items and $items->count()):

?>

<nav>
  <ul>
    <?php foreach($items as $item): ?>
    <li<?php e($item->isOpen(), ' class="active"') ?>>
      <a href="<?= $item->url() ?>"><?= $item->title()->html() ?></a>
      <?php if($item->hasChildren()) : ?>
      <ul>
        <?php foreach($item->children() as $child): ?>
        <li<?php e($child->isOpen(), ' class="active"') ?>>
          <a href="<?= $child->url() ?>"><?= $child->title()->html() ?></a>
        </li>
        <?php endforeach ?>
      </ul>
      <?php endif; ?>
      </li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>