Tags, but the opposite

Hiya,

Trying to get the structure on this new project, and I have a specific element I’m trying to figure out how to do appropriately:

For the structure we’re imagining, each page can be flagged to answer one or more questions (ex: “How can I get help with smoking cessation?” or “What are the clinic hours?”) and we’ll use all that information to populate a big persistent search field.

My difficulty is trying to figure out how to get entries for that field. I’d want something comma delimited, a lot like tags, however unlike tags, it wouldn’t suggest matches. And moreover, it would be very helpful if the panel actually prevented you from duplicating an entry that existed anywhere else.

Any idea on how to go about this?

Maybe this plugin can help you: New Plugin: Select-A-Structure

I used it to have a selectbox with authors in my blog post blueprint like this:

  creator:
    icon: user
    label:
      de: Autor
      en: Author
    type: selectastructure
    structurepage: blog
    structurefield: authors
    optionkey: name

The authors are managed on the blog overview in a structure field:

  authors:
    label:
      de: Autoren
      en: Authors
    type: structure
    entry: >
      {{name}}
    fields:
      name:
        label:
          de: Name
          en: Name
        type: text
      image:
        label:
          de: Bild
          en: Image
        type: image
      info:
        label:
          de: Informationen
          en: Informations
        type: textarea

Imagine authors as questions and store them per page again in a structure field (“…to answer one or more questions…”)?

it might be i don’t completely understand your needs, especially:

Svnt

That does look useful, but not for this. Imagine a site where you have like 100 pages, and they all have one or more strings of metadata assigned to them. I want the panel editor to type in whatever metadata strings they like, but I want the system to prevent the editor from using a string that another page uses.

Ok, then build a custom panel field. Just copy this one and extend the validation: https://github.com/getkirby/panel/blob/master/app/fields/text/text.php

read more about it here: https://getkirby.com/docs/developer-guide/panel/fields

Svnt

I think I understand, but I don’t I’m quite confident my PHP skills to be able to extend the validation. I’m looking at the tags syntax, I think I see where I could comment out the autocomplete stuff, but I’m not sure how I could let the field validate that this string hasn’t been used elsewhere.

why not this plugin?

it can filter on tags (see options from other fields)
https://getkirby.com/docs/cheatsheet/panel-fields/checkboxes

That’s a ways off from what I’m thinking here. I want the page author to be able to type in anything they want as a string that defines that page.

Your validate() method could be something like this (just a rough draft with a hardcoded field):

  public function validate() {
    $siblings = $this->page()->siblings(false);
    $values = $siblings->pluck('intro', ',', true);
    if(!in_array($this->value, $values)) {
      return true;
    } else {
      return false;
    }
  }

Hey @texnixe!

Thanks! I’m getting close here to the solve, but haven’t got there yet. My code’s pretty much what you provided:

public function validate() {
    $siblings = $this->page()->siblings();
    
    $values = $siblings->pluck('terms', ',', true);
    if(!in_array($this->value, $values)) {
      return true;
    } else {
      return false;
    }
  }

This is preventing me from hitting save when the terms field is identical on two different siblings, but it’s not parsing the array. So I was just able to save this…
Terms: getting legal help,find a lawyer,legal aid,help with lawyer,visit the clinic
when it should have conflicted with this…
Terms: visit the clinic,medical assistance,find medical help,visit the dentist,fill a prescription

Also, I’d actully like to extend this validator to more than just siblings, but when I tried to run the validator on $pages->index(), it told me that it didn’t know what pages meant.

Also also: when the field comes back with an error, can you tell me where I put that error message so it’s not just “Please fill in all fields correctly”?

Ok, first one: $this->value() is just a string, so you would have to make that into an array: explode(',', $this->value(). And then compare the two arrays.

As regards also, try site()->index().
As regards also also, panel()->notify() should do the job.

  public function validate() {
     $pages = site()->index()->not($this->page());

      $values = $pages->pluck('intro', ',', true);

      $currentValues = explode(',', $this->value);
      if(empty(array_intersect($currentValues, $values))) {
        return true;
      } else {
        panel()->alert('Oh no, how dare you!');
        panel()->redirect('pages/' . $this->page() . '/edit');
        return false;
      }
    }
3 Likes

Hey @texnixe!

Thank you so much! That makes a lot of sense, and I think I can make it work from here. I’ve got a much better understanding of how custom form fields work now, so thanks again.