Menu pages and Subpages

Hi there,

I’m struggling with the following. Subpages of a menu item.

I made this menu:

<?php

  // main menu items
  $items = $pages->listed();

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

  ?>
    <div class="menu-button menu-open"><i class="open-icon ion-android-menu"></i><i class="close-icon ion-android-close"></i></div>

    <ul class="flexnav standard dark with-js opacity lg-screen" data-breakpoint="800">
        <?php foreach($items as $item): ?>
            <li class="item-with-ul <?php e($item->isOpen(), 'active') ?>">
                <a href="<?= $item->url() ?>"><?= $item->title()->html() ?></a>
            </li>
            <?php endforeach ?>
    </ul>
    <?php endif ?>

Now I also want to show the subpages (children) of the menu. But: I don’t want to show all the blogpost under the parent ‘Blog’.

I know I have to use the nested menu:

<?php

// nested menu
$items = $pages->listed();

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

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

      <?php

      // get all children for the current menu item
      $children = $item->children()->listed();

      // display the submenu if children are available
      if($children->isNotEmpty()):

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

    </li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>

How can I decide which children I want to show. For example: Show children except for the blog and shop.

Thanks!

If the blog posts and the shop pages have unique templates, you can use filters to exclude them from the foreach loop. There are other ways to filter them out, not just by template, just something unique to those pages that you can take for granted. Don’t use something like the page title, since this can be changed by an editor and would render the filter inoperable if someone did change it.

Heres a guide to filtering:

One way is to use a toggle field on all the main pages of the site (ie ones that have children or are at the top level). You can use that toggles true/false status in the loop to decide whether or not its children should also be in the menu.

Another way is to use structure fields to build up the menu. Theres an excellent new cookbook guide on this over here…

1 Like

If it’s just those two pages, you can use a simple if statement:

      // display the submenu if the item is not blog or shop and if children are available
      if(! in_array($item->id(), ['blog', 'shop']) && $children->isNotEmpty()):

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

    </li>
    <?php endforeach ?>
  </ul>
</nav>
<?php endif ?>

Instead of using the id (if this can possibly change), you can also check for intended template or a another unique identifier.

1 Like

Thanks for your help @jimbobrjames. Will try your suggestions!

As always, thank you very much @texnixe. Really impressed by your help (always).