1

I have a drupal 8 site that uses the paragraphs module. In one of the paragraph is a field that contains an autocomplete field. It is already set up to reference a small list of Content Types. For example, "News, Events, Product, Image" are four referenced for the autocomplete.

On another paragraph, it includes this autocomplete but also has a field called "Select a Content Type", it lists out ALL the content types. This is used on the content type. When someone adds a new content they are presented with a list of all the content types as a checkbox and the autocomplete field.

My goal is to only display the selected results from the "select a content type" field onto the autocomplete field.

So when a user selects a "news" / "events" / "Product" / "image" from the "Select a content type" field, the autocomplete only displays nodes of what was selected. If I select news then only news appears when I start entering data. If I select News and events, then both will show. If I select none then a custom message appears.

I have looked around and found how to overwrite getReferenceableEntities but I don't see a way to pass two variables: one from the checkbox field and the autocomplete entered value.

I suspect there will be JS involved to have the form send both checkbox and search value over but I don't know where to begin.

  • If you used 4 unique reference fields, you could use Twig and a hook form to control both the display and form display based on selection. But, this would show two autocomplete fields if two content types were selected, would that be horrible UX for you? Only offer this as low hanging fruit. Would take little coding... – Prestosaurus May 15 '19 at 19:19
  • @Prestosaurus I appreciate that feedback. It already has an established codebase that displays this one field already. I am just modifying an existing environment and don't want to track and modify it to fit X number of reference fields. Especially since that reference field could potentially grow or shrink at any given time. I am going the VIEWS route I think this will get me closer but I do need help knowing what JS changes I need to init for the view to receive a second argument. – Simon Song May 15 '19 at 20:14
0

I don't know the exact UX you are going for, but with a mix of conditional fields an entity reference view and some hook_views_pre_view I think you can accomplish what you need.

First create a new view that has a display that is an Entity Reference. see: How to create a view type of Entity reference display?

  • make sure that the Entity reference view filter returns the 4 content types you are interested in.
  • Add a contextual filter for the content type

Second, configure the node autocomplete field to use the content entity reference view as it's datasource

this is an example of configuring another node's field to use an entity reference view as a datasource

Note: if you are setting up your form some other way (its not a node form display) you'll have to set this up in code - i don't have an example handy.

Lastly, when the user makes a content type choice store that value somewhere (session, on the content, whatever) so that the choice is accessable via the hook_views_pre_view hook.

/**
 * Implements hook_views_pre_view().
 *
 * @param ViewExecutable $view
 * @param QueryPluginBase $query
 * @return void
 */
function MY_MODULE_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  // Get the content type choice from wherever you stored it
  $content_type = "SOME_TYPE";
  // add a filter to the brand view for the supplier's ICs
  if($view->id() == 'MY_CUSTOM_VIEW' && $view->getDisplay()->display['id'] == 'entity_reference_1') {
      $args = [$content_type];
  }
}
  • Yesterday after posting my question I changed the reference method to use views and contextual filters. This Answer is perfect and does what I need except for the last part. I think this is the UX part you don't know about. The "content type choice" is on the same page as the autocomplete field. It may appear afterwards but once I add the autocomplete and the end user decides they need to change it then I want the autocomplete to reflect that. I feel like this hook may not work. Or am I wrong about that and the autocomplete always refer back to hook_views_pre_view() – Simon Song May 16 '19 at 15:11
  • so the autocomplete callback is an ajax to the resultset returned by this view. So if you've stored the user's content type choice somewhere that the hook can read from (session, cookie, formstate, whatever) then this hook should fire before returning results to the widget. – Francis Yaconiello May 16 '19 at 16:47
1

MYMODULE/src/EntityAutoCompleteMatcher.php:

class EntityAutocompleteMatcher extends \Drupal\Core\Entity\EntityAutocompleteMatcher {

  /**
   * Gets matched labels based on a given search string.
   */
  public function getMatches($target_type, $selection_handler, $selection_settings, $string = '') {

    $matches = [];

    $options = [
      'target_type'      => $target_type,
      'handler'          => $selection_handler,
      'handler_settings' => $selection_settings,
    ];

    $handler = $this->selectionManager->getInstance($options);

    if (isset($string)) {
      // Get an array of matching entities.
      $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS';
      $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10);

      // Loop through the entities and convert them into autocomplete output.
      foreach ($entity_labels as $values) {
        foreach ($values as $entity_id => $label) {

          $entity = \Drupal::entityTypeManager()->getStorage($target_type)->load($entity_id);
          $entity = \Drupal::entityManager()->getTranslationFromContext($entity);

          // Only return bundle types we want.
          if ($entity->bundle() == 'page') {
            $matches[] = ['value' => $label, 'label' => $label];
          }
        }
      }
    }

    return $matches;
  }

}

More work would need to be done, but this shows where we can control the returned list of referenced entities.

See:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21EntityAutocompleteMatcher.php/8.8.x

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.