Add a panel field in a condition

I want to add a field to a panel page. But i want to add the field optionally. I found the conditions you can use show and hide fields when another element on the same page is set to something, but i want it on a global scope.

In my blueprint i have a field:

category:
  label: Thema
  type: checkboxes
  options: query
  query: site.index.template('category')

I want to disable the option when there are no categories. So i added a pagemethod to my plugin and a when condition to my field.

'pageMethods' => [
    'hascategories' => function () {
        return 'yes';
    },
]

when:
    hascategories: 'yes'

But no cigar. I can only get it to work on a page field on the current page. Can i use an external option to show or hide a panel field?

The when property needs to go in the blueprint, not in the method. Sorry if i have misunderstood you, but it looks like thats what you have done from your code examples.

I’ve never used the conditional fields, so this is a wild guess.

AFAIK the check for those conditional fields is done only in the browser. So, it works only if there’s a piece of content that gets loaded in the panel.

A pageMethod (or a custom method in a page model) returns something when you call it on the server, but what it returns is not part of the page content, therefore your ‘yes’ is never loaded by the panel and therefore it can’t be used to hide or show your fields.

tldr;
conditional fields don’t query the server.


If all this is true, your only way around this would be to update your page content in a hook, updating the hascategories value whenever it has to change. Then load that value via a hidden field in your page blueprint

Yes, that would be the way forward.

However, depending on the count of pages that need to be updated when your “global value” changes (if it’s big), it might be worth trying something else:
maybe it’s possible to overload the children function of your parent page model to return virtual pages (that actually then map to the real pages) and inject your hascategories value there.
Something like this (absolutely not tested):

function children() {
  $realChildren = parent::children();
  $childrenData = [];
  foreach($realChildren as $c) {
    $childrenData[] = [
      'slug' => $c->slug(),
      'template' => $c->intendedTemplate(),
      'model' => $c->intendedTemplate(),
      'num' => $c->num(),
      'draft' => $c->isDraft(),
      'content' => array_merge( $c->content()->data(), [ 'hasCategories' => 'yes' ])
    ];
  }
  return Pages::factory($childrenData, $this);
}