Select field query to retrieve list of all templates present in a pages collection?

I have a page with subpages that use varying templates:

content/a/page.txt
    content/a/a/subpage_type1.txt
    content/a/b/subpage_type1.txt
    content/a/c/subpage_type2.txt
    content/a/d/subpage_type1.txt
    content/a/e/subpage_type3.txt
    content/a/f/subpage_type3.txt

In my blueprint I’d like to provide a select field that renders the actually used template names of the subpages into its options. So, if a page only has subpages of type 1+2, only those appear in the select field; if a page has three types of subpages, all three appear:

subpage_type1
subpage_type2
subpage_type3

pluck would allow me to create a select field that lists all values in use in some field within the content files (e.g. for tags). But how do I get something similar that returns all template names in a collection of pages?

you could add a custom method like “allChildrenTemplates” to the model of the parent page returning an array. then call that function in the blueprint query.

Great hint, thank you @bnomei - that was exactly the pointer I needed to learn solving this!

For the possible benefit of others, here’s what I did and works (I ended up using a page method rather than a page model, as this is used in multiple blueprints):

'pageMethods' => [
  'allChildrenTemplates' => function() {
    foreach ( $this->children() as $childpage )
      $templatenames[] = $childpage->template()->name();
    return array_unique( $templatenames );	
  }
]

And in my blueprint:

fields:
  filter:
    label: Filter for one of the subpage types
    type: select
    options: query
    query: page.allChildrenTemplates

Mind once again blown by Kirby’s straightforward extensibility! :star_struck:

2 Likes

I should have found (or better read) this post 2 hours earlier - incredible helpful!

The only thing I had to change was: $templatenames[] = $childpage->intendedTemplate()->name(); because I was getting the parent template. Any idea why?

I don’t really have an idea why you’d get the parent template, but intendedTemplate() is definitely the more robust way in any case as it also works in case no template exists for a page’s blueprint. Thank you for pointing that out :slight_smile: