Set Category and Tag (Taxonomies) as required

Hi!
I’ve been using Grav for a month now and I’m becoming a bigger fan from day to day.
Since a few days I started playing around with Blueprints to override the default behavior of some fields in the admin panel.
My current goal is to set both taxonomy fields (“Category” and “Tag”) as required (indicated by a red star next to the text field) for pages of type “Item”.

Currently, my blueprint file looks like this:

extends@: item

form:
  fields:
    tabs:
      fields:
        options:
          fields:
            taxonomies:
              fields:
                header.taxonomy:
                  validate:
                    required: true

But this validation becomes true when “Category” or “Tag” is filled in. I am looking for a way to set both fields as required.
Does anyone know of a way to do this?

Thanks a lot, Phillip

header.taxonomy.author:
              ordering@: header.title
              type: select
              label: Autor
              size: medium
              data-options@: ['\placeOfMyAuthorsList']
              options:
                '': ''
              validate:
                required: true

Thats how I manage to have Author as required.

ordering@: header.title moves Author select field to Content tab

hope this will help

1 Like

Hi,
thank you very much for your answer, but unfortunately it does not bring me any further.
I want to use the two fields “Category” and “Tag” and not create my own. Overwriting the two fields with custom headings is unfortunately not an option either, as I want to use the “Taxonomy List” plugin for example. This needs entries in the taxonomy map.
Or maybe I misunderstood your answer?

            header.taxonomy.category:
              type: select
              label: Category
              multiple: true
              array: true
              selectize:
                create: true
              options:
                  - Option1
                  - Option2
                  - Option3

            header.taxonomy.tag:
              type: select
              label: Tag
              multiple: true
              array: true
              selectize:
                create: true
              options:
                  - Option1
                  - Option2
                  - Option3




            taxonomies:
              replace@: true



Just adjust with your blueprint. Dont forget that in admin settings U need to have category and tag in taxonomies field

             validate:
                required: true

Forgot that U want to have them required - just add this on each and you will set both fields as required

Hello,
your answer goes in the right direction, but is still not quite what I want.
In your example, the user can select one of three static values (“Option 1”, “Option 2”, “Option 3”). However, I want the user to be able to select the “Category” and “Tag” tags previously created on other pages - that is, the default behavior of the Taxonomy tags.
When I create a new tag in one of the text fields you created, the tags don’t appear in the dropdown menu when another page is created - only the three static values are displayed.
I think something like a “data source” is missing in these text boxes.

What works: The selected tags are recognized by the Taxonomy List plugin.

Youuup thats how its works … You can always write Option4 in field to add different from predefined. Not sure if it possible to get exactly what you want without custom plugin to manage tags - something like I have for Author taxonomy from my 1st post… but I might be wrong as Im new here (using Grav from 1 month only)

1 Like

Hello,
first of all, thank you for your efforts.
You pointed me to your first post. Do I understand you correctly when I say:
I need to write a php script with a static function that returns the values of a taxonomy list (as an array) and define the script in the argument “data-options@”?
Is this correct?

Do you know a good documentation or example to read me into this?

@pireba, Have a look at Using Function Calls (data-*@)

Hello,
that was a good address to start with, thank you.

In my setup I created a theme that overrides Quark (I call it CustomQuark). In its php file I added a function “taxonomyTest”, which I successfully included in the blueprint - I can see the placeholder in the dropdown menu of the text field.
But now I need a way to get every created tag of a taxonomy. I have tried the following:

<?php
namespace Grav\Theme;

use Grav\Common\Grav;
use Grav\Common\Theme;

class CustomQuark extends Quark
{

        public static function taxonomyTest()
        {
                $taxonomy = Grav::instance()['taxonomy']->taxonomy();
                Grav::instance()['log']->info("Taxonomy: " . implode(",", $taxonomy));

                $pages = Grav::instance()['pages']->all();
                Grav::instance()['log']->info("Pages: " . $pages);

                return array (
                        'PH' => 'Placeholder',
                );
        }
}
?>

Output in log:

[2022-11-11 21:54:52] grav.INFO: Taxonomy:  [] []
[2022-11-11 21:54:52] grav.INFO: Pages:  [] []

Why are both variables empty?

@pireba, Instead of trying to implement a “custom” Taxonomy field by yourself, you can add some validation using a plugin.

Try and adapt the following:

  • In case not all Taxonomy taxons are required, add to the yaml file of the plugin the following:

    requiredTaxons: [category, tag]
    
  • Subscribe to event ‘onAdminSave’:

    if ($this->isAdmin()) {
        $this->enable([
            'onAdminSave' => ['onAdminSave', 0],
        ]);
    
        return;
    }
    
  • Add the following function to handle the onAdminSave event:

    public function onAdminSave(Event $event)
    {
      // Only run validation when a page is being saved.
      if (!$event['object'] instanceof PageObject) {
        return;
      }
    
      /** @var PageObject */
      $page = $event['object'];
    
      // Only run validation on specific page type, eg. blog item.
      if ($page->template() !== 'item') {
        return;
      }
    
      $taxonomy = $page->header['taxonomy'] ?? [];
    
      $taxons = $this->config->get('plugins.validate.requiredTaxons', []);
    
      foreach ($taxons as $taxon) {
        if (!isset($taxonomy[$taxon])) {
          $capitalised = ucfirst($taxon);
          throw new \Exception("Field '$capitalised' is required.");
        }
      }
    }
    

    The message of the Exception will be shown in a red banner in Admin at the top of the page.

@pireba, To respond to your issue wrt the empty Taxonomy values in your static function…

Try the following function inside your theme (or plugin):

public static function taxonomyValues(string $taxon, string $fieldType)
{
  /** @var Grav */
  $grav = Grav::instance();

  /** @var Admin */
  $admin = $grav['admin'];
  $admin->enablePages();

  /** @var Taxonomy */
  $taxonomy = $grav['taxonomy'];

  $keys = $taxonomy->getTaxonomyItemKeys($taxon);
  $values = [];

  foreach ($keys as $key) {
    if ($fieldType === 'select') {
      $values[$key] = $key;
    } else {
      $values[] = [
        'text' => $key,
        'value' => $key,
      ];
    }
  }

  return $values;
}

In combination with the following field definitions:

data-options@: ['\Grav\Theme\Quark::taxonomyValues', 'category', 'select']
data-options@: ['\Grav\Theme\Quark::taxonomyValues', 'tag', 'selectize']

Notes;

  • Replace Quark with the name of your theme.
  • The 2nd parameter select|selectize, might not be needed in your case. It’s just to show that different returns types are required depending on the field type.

Hi!
Nice, it works! Thanks a lot for that!

I think the reason it didn’t work for me are these two lines:

  $admin = $grav['admin'];
  $admin->enablePages();

Can you tell me why I need to call “enablePages()”? I can’t find any API documentation for the admin plugin class…

Your first solution is good to know, but I prefer the second one because any logic is in the blueprint file. Only the creation of the array is written in PHP code.

For those who want the same behavior as me, here is my working code:

Blueprint file (user/themes/custom_quark/blueprints/item.yaml):

extends@: item

form:
  fields:
    tabs:
      fields:
        options:
          fields:
            taxonomies:
              fields:
                
                header.taxonomy:
                  unset@: true
                
                header.taxonomy.category:
                  type: select
                  label: Category
                  selectize:
                      create: true
                  multiple: true
                  array: true
                  data-options@: [ '\Grav\Theme\CustomQuark::getTaxonomy', 'category' ]
                  default: [ 'blog' ]
                  validate:
                    required: true
                
                header.taxonomy.tag:
                  type: select
                  label: Tag
                  selectize:
                      create: true
                  multiple: true
                  array: true
                  data-options@: [ '\Grav\Theme\CustomQuark::getTaxonomy', 'tag' ]
                  validate:
                    required: true

PHP file (user/themes/custom_quark/custom_quark.php):

<?php
namespace Grav\Theme;

use Grav\Common\Grav;
use Grav\Common\Theme;

class CustomQuark extends Quark
{
	public static function getTaxonomy(string $tag) {
		$grav = Grav::instance();

		$admin = $grav['admin'];
		$admin->enablePages();

		$taxonomy = $grav['taxonomy'];

		$keys = $taxonomy->getTaxonomyItemKeys($tag);
		$values = [];

		foreach ($keys as $key) {
			$values[$key] = $key;
		}

		sort($values);
		return $values;
	}
}
?>
2 Likes

@pireba,

Can you tell me why I need to call “enablePages()”?

For performance reasons, pages are not being initialized when using Admin. Hence the Taxonomy is not set. Using $admin->enablePages(); will force Admin to initialize the pages.

Hello,

I tried to implement this automatic option populating. It works fine with select, but it doesn’t seem to work with selectize.
The php function in my theme is the same than yours, and my yaml look like:

header.test:
  type: selectize
  autocomplete: on
  style: vertical
  label: test
  data-options@: ['\Grav\Theme\NixTemplate::taxonomyValues', 'artiste','selectize']
  validate:
    type: commalist

If i dump the $values in the php, I can see an “array of array”:

array:2 [▼
  0 => array:2 [▼
    "text" => "artiste1"
    "value" => "artiste1"
  ]
  1 => array:2 [▼
    "text" => "artiste2"
    "value" => "artiste2"
  ]
]

But if i click in the field in the admin, I can’t see any suggestion of completion, do you know what I am doing wrong?

@nix, This topic has already been closed/solved. Please open a new topic with a proper title describing your specific problem and add a reference in the content of the topic to this topic for context.

You’re right, sorry for that! Here is the new topic.