One Page subpages/parts hide from menu, but regular subpages not

Hello, I am building One Page like from this tutorial

Actually, I finished it, and made it work like a page builder, but have one issue.

How to hide from the menu only page builder subpages/parts but not regular subpages.
My menu is based on Nested Menu.

I can easily hide all with $site->children()->findBy('template', 'builder'); but what I want is only to hide parts subpages.

Thank you in advance.

There are different ways to handle that, using a special template for the partials is one.

Other options:

  • listed vs unlisted page statuses
  • an extra toggle field “include in menu” and then to filter subpages by that field
  • put partials in partials folder and exclude that folder
1 Like

Thank you very much, @texnixe you helped me a lot.

I used the template solution for blueprint listing parts-subpages and regular subpages separately.
But for menu exclusions of parts-subpages, I am trying to make something programmatically, so I can just add new partials templates without worry.

Check this idea (it doesn’t work currently):

$parts = $site->children()->filter(function ($partial) {
return str::startsWith($partal->template(), 'builder-');
});
$children = $item->children()->listed()->not($parts);

The idea is to filter page templates that start with “builder-” and exclude them from menu.

Can you help to get it to work?

There’s a typo and you have to compare to template name, so try:

$parts = $site->children()->filter(function ($partial) {
return str::startsWith($partial->template()->name(), 'builder-');
});
$children = $item->children()->listed()->not($parts);

But still, what is $item in this case? And filtering $site->children() doesn’t make sense either. You probably want to use $item here as well.

1 Like

Yes, you are right about $item. But still, it doesn’t work. Although, it seems to me that it is pretty close.

Here goes the full code from menu snippet

<?php

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

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

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

      <?php

      // get all children for the current menu item
      $parts = $item->children()->filter(function ($partial) {
      return str::startsWith($partial->template()->name(), 'builder-');
      });
      $children = $item->children()->listed()->not($parts);
      $blog = $site->children()->findBy('template', 'blog');

      // display the submenu if children are available
      
      if(!$item->isHomepage() && !$item->is(page($blog)) && $item->hasVisibleChildren()):

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


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

<?php endif ?>

Could you be a bit more specific, please? What exactly does not work as expected?

Make some tests like

dump($parts);
dump($children);

to check what sort of results you get.

1 Like

The code still doesn’t hide Builder partial subpages (parts) from the dropdown navigation on the website frontend.

For dump($parts); I get empty objects

Kirby\Cms\Pages Object
(
)

For dump($children); there are all subpages

Kirby\Cms\Pages Object
(
    [0] => page-builder/text
    [1] => page-builder/hello
    [2] => page-builder/columns
)

Subpages “text” and “columns” are page builder subpages, and “hello” is regular subpage.

Then it is obvious the $parts function doesn’t work. I see that.

Thank you @texnixe very much for your help, you did help me a lot.

I am testing the best option for building a base for page builder, and I am comparing One Page option you provided in Cookbook versus Page Builder plugin.

Because I see there are many implications when doing it as One Page solution (also for sitemap, more effort for maintenance…), I will go for the Page Builder plugin.

The Page Builder is a good alternative if your subpages do not have a complicated structure, yes. Note that the Page Builder plugin currently doesn’t work together with the Editor plugin

It just dawns on me why $parts is empty. Since there are no builder-xxx templates, you would have to use intendedTemplate() instead.

$parts = $item->children()->filter(function ($partial) {
      return str::startsWith($partial->intendedTemplate()->name(), 'builder-');
});
1 Like

Bravo! This solution is working. :slight_smile:

Great work, @texnixe you are gold here!

You are so right, those are not templates, those are snippets.

Well, I should have seen that right from the beginning, but sometimes I’m a bit slow on the uptake :see_no_evil:

1 Like