Modifying “Panel Samples: One pager” to use existing pages as parts?

Hello fellow Kirby enthusiasts,

I’m kinda struggling with one concept/idea I came up with yesterday. Basically I would like to create something like a dynamic showcase/portfolio generator in the panel, i.e. I would like to create a new page with only a selection of all available projects (pages), and ideally I could also rearrange the position of each project (page) manually in the panel.

After browsing the reference I came up with the One pager Panel Sample which already looks quite promising. Tried it, works as promised.

Now I’m thinking about how to modify this setup in two regards:

First, the hard part: Instead of adding new parts as subpages, “insert” new parts from a global selection of pages e.g. from content/all_projects_hidden_folder/ … (EDIT: I fear choosing between “inserting” pages and adding new parts as subpages is not possible, unfortunately.)

Second, the easier part: Modify the Pages section to be sortable. I thought of sortable: true as described in the reference, but somehow adding this to my .yml didn’t work (nothing changed).

Would be happy and thankful about some feedback. I don’t think this is some hard problem, I’m just a little stuck I fear.

Thank you so much!

Let’s say you have a projects page with subpages.

If you now create a new page with a structure field, in which you can select from these projects, you could also sort them as you like and add as many as you like.

Excuse me, how would I select these subpages from/inside a structure field?

In case of sections (as in the One pager sample), I stumbled upon the parent option … though I’m not yet sure if I understand this option correctly and if this would work for me. Need to try out.

EDIT: As I already thought, seems it does not work via the parent option as this modifies the parent page itself and not another “virtual instance” of the content. Another problem her is that only subpages of the parent page are listed but not subpages which are having subpages themselves.

Inside your structure field, you could use a pages field (not section) with a query option that queries the children of the projects page.

You could also just use a pages field as standalone without the structure field, as that would also allow you to sort the selected projects.

The strucuture field is useful if you want to add additional information.

1 Like

The following blueprint seems to work pretty well.

title: Selection

fields:
  content:
    label: Content
    type: pages
    image: false
    query: site.find("archive")

You could also just use a pages field as standalone without the structure field, as that would also allow you to sort the selected projects.

Should try that as well.

EDIT: I just realize that’s what I did, heh.

Thank you very much, @texnixe.

@texnixe Think I could need one last piece of advice.

I’d like to list the contents of all children as well as grandChildren in their respective order. I fear the following snippet does not keep the order. Any quick advice on how I could achieve this with only one foreach?

<?php foreach ($page->grandChildren() as $part) : ?>
<?php snippet($part->intendedTemplate(), compact('part')) ?>
<?php endforeach ?>
<?php foreach ($page->children() as $part) : ?>
<?php snippet($part->intendedTemplate(), compact('part')) ?>
<?php endforeach ?>

Thank you for your help!

without ever having used merge(), i feel like this could be what you’re looking for? https://getkirby.com/docs/reference/objects/pages/merge

Not quite sure what you want to achieve here? Render the children first and then the grandchildren that belong to each child? Or vice versa?

As an abstract example, I have the following order in which I’d like my projects to be displayed:

– project with subpages with images
– project with images
– project with subpages with images
– project with images
– project with images
– project with subpages with images

In case of the snippet I posted above, the problem is that the order is changed to first display all of the projects with subpages and then the projects without subpages, right? How would I prevent this re-ordering?

Like this?

<?php foreach ($page->children() as $part) : ?>
<?php snippet($part->intendedTemplate(), compact('part')) ?>
<?php if ($part->hasChildren()) : ?>
    <?php foreach ($part->children() as $partChild) : ?>
    <?php snippet($partChild->intendedTemplate(), compact('partChild')) ?>
    <?php endforeach ?>
<?php endif ?>
<?php endforeach ?>

Hmm … how about using an if/else condition here …

<?php foreach ($page->children() as $part) : ?>
  <?php if ($part->hasChildren()) : ?>
    <?php foreach ($part->children() as $partChild) : ?>
    <?php snippet($partChild->intendedTemplate(), compact('partChild')) ?>
    <?php endforeach ?>
  <?php else: ?>
    <?php snippet($part->intendedTemplate(), compact('part')) ?>
  <?php endif ?>
<?php endforeach ?>

Does that make sense, I wonder … sorry, maybe I’m just overthinking something here.

Maybe, but I’m still not sure how that code snippet relates to the original question. Your if-else code and my code do different things and it depends on what you want to achieve.

Sorry for the confusion. In regards of the original question, that snippet does not really help. It does work for the original hidden_folder_with_all_projects section blueprint. I wanted to create this first, then modify it to be able to create the “virtual instances” I asked for above.

For the “virtual instance” page in which I can choose which projects to insert (via fields … type: pages), I would have to rewrite the snippet to something like:

<?php $parts = $page->content()->toPages() ?>
<?php foreach ($parts->children() as $part): ?>
<?php //foreach ($page->content()->toPages() as $part): ?>
<?php snippet($part->intendedTemplate(), compact('part')) ?>
<?php endforeach ?>

Unfortunately, this results in: Call to a member function intendedTemplate() on null … and I’m trying to fix that since around an hour without success.

Here’s the snippet for that “virtual instance” blueprint, again:

title: Showcase

fields:
  content:
    label: Content
    type: pages
    image: false
    info: "{{ page.intendedTemplate }}"
    query: site.find("archive")

The intended template is shown in the panel. Not sure why the foreach does not give me proper page objects. :thinking:

For reference: https://getkirby.com/docs/reference/panel/fields/pages

Seems content is a reserved name and cannot be used for naming a field. :see_no_evil:

Yes, you either have to rename your field or fetch it like this:

$page->content()->get('content')->toPages();
1 Like