0

My Goal:

I want to create a customized entity_autocomplete form field to better fit my needs compared to the default one - making some modifications to the HTML and JS that's being used, as well as how submissions are handled.

Specifically, I want to do something like this but I need more control over the backend, and everything...

What Drupal can do:

Drupal's default entity autocomplete already lets the user type 2 letters, and it finds all entities that contain these 2 letters.

Entity Reference Example

My Problem:

Unfortunately I have trouble figuring out how to use the existing "search feature" if you will call it that.

Some Considerations:

I looked into using search API, but this was similarly overwhelming. Considering that this functionality I'm looking for is already built into Drupal, I figure I can just re-implement it, without any additional modules, right? Really, I'm just re-designing the UI. And even if I need to beef it up in the future with a faster, resource saving search engine, I can just replace that aspect of my module/controller. (If someone can point out how to use Search API to do what I need, I'd be happy to listen)

What I've done so far:

I have already created my own custom route that points to a JSON controller which will accept the search parameters.

Based on all my research I figured I need to add use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection; to the top.

I see that DefaultSelection::getReferenceableEntities seems to do exactly what I need it to do.

However, the constructor for this class has 9 different parameters, many of them classes which I know nothing about.

But there is a create method, which apparently allows you to inject configuration data, but also it requires a ContainerInterface.

So here's where I'm lost...

How exactly do I make use of DefaultSelection::getReferenceableEntities in my custom controller?

4
  • There are Drupal modules for the Chosen and/or Select2 JS libs, that turn normal select fields into your screenshot. – Hudri Sep 7 '20 at 19:12
  • @Hudri thanks, sorry I wasn't clear. The screenshow shown is something Drupal already knows how to do. I want to modify the existing Drupal functionality. Specifically I want to achieve this: drupal.org/project/drupal/issues/3023298 but I need to have control over the backend (for example, I want to filter and show only a subset of the entity types) – olli Sep 7 '20 at 20:43
  • 1
    Why don't you simply copy the code of theis method into your own class and adjust it for your needs? – Tobias Krause Sep 15 '20 at 7:31
  • Thank you @TobiasKrause this was a great suggestion! I tried it, and although not feasible it helped me figure out how this works and what it's all about. – olli Sep 15 '20 at 22:08
2

Okay, it took me over 2 weeks to get to the bottom of this, but turns out, that DefaultSelection::getReferenceableEntities is just a wrapper for Drupal::entityQuery. This becomes especially clear when realizing that DefaultSelection::getReferenceableEntities makes a call to DefaultSelection::buildEntityQuery. And this method is only a complicated way to make a customized query.

So for my purposes, all I had to do was learn about entity queries. Here's how I ended up performing a search:

For taxonomy terms

            $query = \Drupal::entityQuery('taxonomy_term'); 
            $query->condition('vid', 'my_taxonomy_terms'); //select the collection
            $query->condition('name', $search_term, 'CONTAINS'); //searching the title for a search term
            $term_ids= $query->execute();
            $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($term_ids);  //process the nodes however is desired

            $result = [];

            foreach($terms as $term){
              $result[$term->id()] = $term->getName();
            }

            return $result;

For other entities and nodes

            $query = \Drupal::entityQuery('node'); 
            $query->condition('field_somefield', 'somevalue'); //optional condition to filter results by
            $query->condition('title', $search_term, 'CONTAINS'); //searching the title for a search term
            $node_ids = $query->execute();
            $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($node_ids); //process the nodes however is desired

            $result = [];

            foreach($nodes as $node){
              $result[$node->id()] = $node->getTitle();
            }

            return $result; 

Reference: https://api.drupal.org/api/drupal/core!lib!Drupal.php/function/Drupal%3A%3AentityQuery/8.2.x

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.