Checkbox items as menu items

Continuing the discussion from Problem with custom menu:

Hello,

I’m looking to achieve what’s been quoted above - and would appreciate a pointer in how to approach this.

If the file structure is:
Projects

  • Project (Check box categories A, B)
  • Project (Check box categories B, C)
  • Project (Check box categories A, C)

How do you create a menu structure where A, B, and C are sub-menu items of ‘Projects’, each displaying all projects in their category?

That would be something like this, although this solution doesn’t relate to the quote:

<?php $projects = page('projects')->children()->visible(); ?>

<ul>
  <?php foreach($projects->pluck('categories', ',', true) as $category): ?>
  <li>
    Category <?php echo $category ?>:
    <ul>
      <?php foreach($projects->filterBy('categories', $category, ',') as $project): ?>
      <li><a href="<?php echo $project->url() ?>"><?php echo $project->title() ?></a></li>
      <?php endforeach ?>
    </ul>
  </li>
  <?php endforeach ?>
</ul>

This example assumes that each project has a category field that looks like this:

Categories: A, B

Thank you for this. The solution highlights that I didn’t phrase my question quite as intended.

I think I mean “How do you create a menu structure where A, B, and C are sub-menu items of ‘Projects’, each linking to a page displaying all projects in their category?”

Projects

  • A
  • B
  • C

All you need is to superpose the main menu structure then:

<nav class="menu">
  <ul>
    //get all main pages
    <?php foreach($pages->visible() as $p): ?>
      <li>
        <?php echo $p->title() ?>
        //check if page is projects page
        <?php if($p->is('projects')): ?>
          //create submenu for categories
          <ul class="category-submenu">
            <?php $projects = $p->children()->visible(); ?>
            <?php foreach($projects->pluck('categories', ',', true) as $category): ?>
              <li><?php echo $category ?>
                //create submenu for Project pages for each category
                <ul>
                  <?php foreach($projects->filterBy('categories', $category, ',') as $project): ?>
                    <li><a href="<?php echo $project->url() ?>"><?php echo $project->title() ?> </a></li>
                  <?php endforeach ?>
                </ul>
              </li>
            <?php endforeach ?>
          </ul>
        <?php endif ?>
      </li>
    <?php endforeach ?>
  </ul>
</nav>

Hmm, this is giving a long error, which says:

Fatal error: Uncaught TypeError: Argument 1 passed to PageAbstract::is() must be an instance of Page, string given, called in …/site/snippets/menu.php on line 20 and defined in …/kirby/core/page.php:768 Stack trace: #0 …/site/snippets/menu.php(20): PageAbstract->is(‘projects’) #1 …/kirby/toolkit/lib/tpl.php(22): require(‘…’) #2 …/kirby/helpers.php(13): Tpl::load(‘…’, Array, false) #3 …/site/snippets/header.php(23): snippet(‘menu’) #4 …/kirby/toolkit/lib/tpl.php(22): require(‘…’) #5 …/kirby/helpers.php(13): Tpl::load(‘…’, Array, false) #6 …/site/templates/projects.php(1): snippet(‘header’) #7 …/kirby/toolkit/lib/tpl.php(22 in …/kirby/core/page.php on line 768

Edited out my file structure with “…”

Line 20 is <?php if($p->is('projects')): ?>

Oh, yes, my bad, should be:

<?php if($p->is(page('projects'))): ?>

Ah, that fixed it, thank you!

This gives this kind of menu structure:

Projects

  • Category A
    – Project A B
    – Project A C
  • Category B
    – Project A B
    – Project B C
  • Category C
    – Project A C
    – Project B C
    Other Menu Item 1
    Other Menu Item 2
    Other Menu Item 3

Is it possible to have it so the structure is this:

Projects

  • Category A
  • Category B
  • Category C
    Other Menu Item 1
    Other Menu Item 2
    Other Menu Item 3

Where following the link from ‘Category X’ would take you to the projects page and only display the projects in that category?

I was thinking of using something like the Metafizzy Isotope, but am not sure how to integrate that in this way?

The menu is rather simple. Simply take out the subsubmenu and add a link to the category:

<nav class="menu">
  <ul>
    <?php foreach($pages->visible() as $p): ?>
      <li>
        <?php echo $p->title() ?>
        
        <?php if($p->is(page('projects'))): ?>
          <ul class="category-submenu">
            <?php $projects = $p->children()->visible(); ?>
            <?php foreach($projects->pluck('categories', ',', true) as $category): ?>
              <li><a href="<?php echo $p->url() . '/category:' . $category ?>"><?php echo $category ?></a></li>
            <?php endforeach ?>
          </ul>
        <?php endif ?>
      </li>
    <?php endforeach ?>
  </ul>
</nav>

The filter would work just like the tag example, just with the category field instead of tag.

1 Like

You could use a param like, e.g. category:categoryA and then filter by that param in your controller:

<?php foreach($projects->pluck('categories', ',', true) as $category): ?>
   <li>
      <a href="<?php echo page('projects')->url() . '/category:' . $category ?>"><?php echo $category ?></a>               
  </li>
<?php endforeach ?>

Edit: Lukas beat me to it.

1 Like

Brilliant, I understand now!
Thank you both for your help, and pointing me towards the Tags page in the docs - a treasure trove of information.