Get certain subpages based on category

What would be the best concept to create a list of pages (or pages in a certain directory) which have a shared category? Let’s assume the editor gives a product page a category like
----
category: animal-project (or something else)

And I want to have a page (or dropdown, or widget) where all pages with this category are displayed as a list. What would be the best option?

Thanks in advance!

One. option would. be to display all subpages in that folder by default, and then. have a list of categories. or a select where. the user can select a category and then. filter the list by that category.

An example can be found here: https://getkirby.com/docs/cookbook/tags

The same could be achieved with routes., so the routes would work like virtual subpages.

It really depends on what exactly you want to achieve. Do you want a navigation with these categories so it looks like a standard URL? Or is a URL with a parameter/query string ok?

If your. subpages can have only one category, it might make sense to sort them into category subfolders in the first place. No additional coding required, clean URLS.

Couple of choices really:

  • Use a select field in your blueprint with a pre-determined set of categories. You can either use global fields for this so you only have one list to maintain, or get the value from a master field that is one page only.
  • Use the tags field and let people set the category on the fly.

As for the drop down, it’s pretty easy to populate a select field on the front end, or generate a list via filtering if you want some other kind of menu.

Thanks for all the replies. Lost my connection shortly after posting this and went home for the day. Now ready to continue.

I kind of already have a solution here: https://www.voluntourismus.de/projekte/ it is made with the static site generator lektor. The template uses this code:

<div id="projects-list">
                    <div class="buttons-list">
                        <label><input type="checkbox" id="roundtripButton" name="roundtrip" value="includeRoundtrip" checked>Rundreisen</label>
                        <label><input type="checkbox" id="animalsButton" name="animal" value="includeAnimal" checked>Tierprojekte</label>
                        <label><input type="checkbox" id="socialButton" name="social" value="includeSocial" checked>Soziale Projekte</label>
                        <label><input type="checkbox" id="specialsButton" name="special" value="includeSpecial" checked>Specials</label>
                    </div>
                    <nav>
                        <ul class="nav proj_cards">
                            {% for projekte in site.get('/projekte').children %}
                                <li class="list {{ projekte.programType }}"><a class="proj_list" href="{{ projekte|url }}"><img src="{{ projekte.headerimage }}"> <span class="short_title"> {{ projekte.title }} </span> <span class="short">{{ projekte.description }} </span> </a></li>
                            {% endfor %}
                        </ul>
                    </nav>
                </div>

There are differences of course: it is easy to get the pages from one directory, and like here to give them classes (programType gets a string from the markdown file which has to match) and solve everything with JavaScript regarding filtering. I would like to do the same with kirby, just with pages witch are in different directories and if it is tags or also classes or other stuff: I am happy as long I can do some kind of sorting/filtering without another request to the server. Still to go with tags?

Tags is just an example, you can call them whatever you like, category or whatever. Of course, you can apply JS-based sorting as well and just print the category as a class to filter by.

To get a collection from different parents, you can merge them. There are two ways to achieve this:


<?php 
//Merge two collections
  $exhibitions = $pages->find('exhibitions')->children()->visible()->filterB('now', 'noo');
  $news  = $pages->find('news')->children()->visible();
  $homeflux = new Pages(array($exhibitions, $news));
?>


<?php 
//Appending stuff to a collection:
  $homeflux = new Pages();
  $homeflux->add($pages->find('exhibitions')->children()->visible()->filterBy('now', 'noo'));
  $homeflux->add( $pages->find('news')->children()->visible());
// etc...
?>

Then you can loop through the resulting collection with a foreach loop. If you want to use some sort of template. language like in. your example above, you’d have to install a plugin. By default, Kirby uses PHP, not any template language.

Thanks, I got the appendig-method to work and used the same loop as in my menu. But: I need to go one directory deeper. Do I have to use the sub sub menu code for that?

Not quite sure what you are talking about. Maybe you can post your structure and indicate what exactly. you want to fetch from where? You can. also check. the. docs for different methods like grandchildren()or index().

Oh yes, sorry I meant the grandchildren. Can I do something like:

$homeflux = new Pages();
$homeflux->add($pages->find('directoryx')->grandChildren()->visible());

This line does not get me any results.

If you don’t. get any results, then either the page has no grandchildren. or they are not visible. It. helps if you show your structure.

Ok, perhaps my loop does it wrong. My structure is:

Category1
  -> Country1
         ->Program
  -> Country2
         ->Program
Category2
  -> Country1
         ->Program
  -> Country2
         ->Program

I just want to go through the Programs, nothing above.

I assume I do have to adjust this?:

<ul>
  <?php foreach($homeflux as $item): ?>
    <li><a<?php ?> href="<?php echo $item->url() ?>"><?php echo html($item->title()) ?></a></li>
  <?php endforeach ?>
</ul>

If directoryxyis a category page, then yes.

Sorry, just ohne more thing: <php foreach($homeflux as $item) ?> can I combine $homeflux with grandChildren?

Yes, you can combine any pages collection into a single pages collection, but since I don’t. know. what $homeflux is and how you have defined the grandChildren, I can’t really help you with this. If you need more help, please provide the complete code.

This code only works if I replace “grandChildren()” with “children()”.

<?php
            //Appending stuff to a collection:
            $homeflux = new Pages();
            $homeflux->add($pages->find('Freiwilligenarbeit')->grandChildren()->visible()->filterBy('Kategorie', 'Sozial'));
            // etc...
            ?>

            <ul>
                <?php foreach($homeflux as $item): ?>
                    <li><a<?php ?> href="<?php echo $item->url() ?>"><?php echo html($item->title()) ?></a></li>
                <?php endforeach ?>
            </ul>

Do I have to change the loop?

Where is “Freiwilligenarbeit” in your structure?

right under root - url.tld/Freiwilligenarbeit

So “Freiwilligenarbeit” is one of your categories in this structure?

Category1
  -> Country1
         ->Program
  -> Country2
         ->Program
Category2
  -> Country1
         ->Program
  -> Country2
         ->Program

Yes, sorry I see now I was not specific enough.

Rundreisen
   -> country
      ->program
Freiwilligenarbeit
  -> country
     ->program
and so on

The programs have different categorys like “fun”, “animals” and others. To be able to filter the categories is my goal.

Ok,

$programs = page('freiwilligenarbeit')->grandChildren()->visible();

should. give you all grandchildren = programs of that main page.

I don’t know what you are. filtering by though.

Note: Please do not use capital letters for your uids;

Also, I wonder if your category names are really saved with capital letters in. your content files?