Change record status: 
Project: 
Introduced in branch: 
8.0.x
Introduced in version: 
8.0.0-beta7
Description: 

The autocomplete field widgets provided by the Entity reference module have been refactored into a generic 'entity_autocomplete' Form API element which can be used in regular form structures (i.e. not only in entity forms).

Usage examples:

Provide a basic autocomplete element that matches node titles from all bundles:

$form['my_element'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
  '#default_value' => $entity, // The #default_value can be either an entity object or an array of entity objects.
);

If we want to restrict the matches to a single or a set of bundles, we can use the 'target_bundles' selection setting:

$form['my_element'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
  '#selection_handler' => 'default', // Optional. The default selection handler is pre-populated to 'default'.
  '#selection_settings' => array(
    'target_bundles' => array('article', 'page'),
  ),
);

If we want to allow an input of multiple entity labels into the element (commonly known as "tagging" fields), we set the '#tags' property to TRUE (its default value is FALSE):

$form['my_element'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
  '#tags' => TRUE,
);

If we want to allow an input of an entity label that does not exist yet but can be created "on the fly" on form submission, the '#autocreate' property can be used:

$form['my_element'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'taxonomy_term',
  '#autocreate' => array(
    'bundle' => 'tags', // Required. The bundle name for the new entity.
    'uid' => <a valid user ID>, // Optional. The user ID for the new entity, if the target entity type implements \Drupal\user\EntityOwnerInterface. Defaults to the current logged-in user.
  ),
);

Other changes:

  • The entity_reference.autocomplete service has been moved out of the Entity reference module and renamed to entity.autocomplete_matcher.
  • The Autocomplete and Autocomplete (Tags style) field widgets have also been moved outside the Entity reference module.
  • The autocomplete_type widget setting which was previously needed as part of the autocomplete path has been removed.
Impacts: 
Site builders, administrators, editors
Module developers
Themers

Comments

mikat’s picture

Here is an example how to use the entity reference as a field in a custom block.


namespace Drupal\my_project\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Block\BlockPluginInterface;
use Drupal\Core\Form\FormStateInterface;

use Drupal\node\Entity\Node;

/**
 * My custom block
 *
 * @Block(
 *   id = "my_block",
 *   admin_label = @Translation("My custom block"),
 * )
 */
class MyBlock extends BlockBase implements BlockPluginInterface {

  /**
   * @return array
   */
  public function build() {
    return array(
      '#markup' => $this->t('Hello, World!'),
    );
  }

  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $form = parent::blockForm($form, $form_state);

    $config = $this->getConfiguration();  // Get stored settings

    $entity = Node::load($config['entity_reference']); // Load entity

    $form['entity_reference'] = array(
      '#title'  => 'Place field title here',
      '#description' => $this->t('Place field description here.'),
      '#type' => 'entity_autocomplete',
      '#target_type' => 'node',
      '#default_value' => $entity, // The #default_value can be either an entity object or an array of entity objects.
      '#selection_settings' => array(
        'target_bundles' => array('page'),
      ),
    );
    
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    parent::blockSubmit($form, $form_state);
    $values = $form_state->getValues();

    foreach ($values as $index => $value) {
      $this->configuration[ $index ] = $value;
    }
  }
}
vivek panicker’s picture

//$member stores the target_id of the particular user
 $entity =  \Drupal\user\Entity\User::loadMultiple(); // Load all user entities
 foreach ($entity as $key => $user) {
    if($user->id() === $member){
       $member = $user; //the user entity which I want is now stored in member
       break;
     }
 }

$form['member'] = array(
      '#type' => 'entity_autocomplete',
      '#target_type' => 'user',
      '#title' => $this->t('Member'),
      '#required' => 'true',
      '#default_value' => $member,


);
japicoder’s picture

After reading the code a bit, I have a working example that builds a entity reference field for users, filtered by one or more roles:

    $roles = ['editor', 'publisher', 'superhero'];

    $form['therapists'] = array(
      '#title' => $this->t('My user'),
      '#type' => 'entity_autocomplete',
      '#required' => TRUE,
      '#target_type' => 'user',
      '#default_value' => $entities,
      '#selection_handler' => 'default:user',
      '#selection_settings' => [
        'include_anonymous' => FALSE,
        'filter' => [
          'type' => 'role',
          'role' => $allowed_roles,
        ],
      ],
    );
rajeshreeputra’s picture

$roles = ['editor', 'publisher', 'superhero'];
$term_id = '101';
    $form['therapists'] = array(
      '#title' => $this->t('My user'),
      '#type' => 'entity_autocomplete',
      '#required' => TRUE,
      '#target_type' => 'user',
      '#default_value' => $entities,
      '#selection_handler' => 'default:user',
      '#selection_settings' => [
        'include_anonymous' => FALSE,
        'filter' => [
          'type' => 'role',
          'role' => $allowed_roles,
          'field_term' => $term_id,
        ],
      ],
    );
liquidcms’s picture

$roles, $allowed_roles

hardcoredev’s picture

If looking to use a View to filter results, this works for 8.5.5

$element['item_user'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'user',
  '#selection_handler' => 'views',
  '#selection_settings' => [
    'view' => [
      'view_name' => 'users_by_name',
      'display_name' => 'member',
      'arguments' => []
    ], 
    'match_operator' => 'CONTAINS'
  ],
  '#default_value' => $user_object
];
matthieuscarset’s picture

It is hard to find a working example of code using Views' entity reference plugin.

Thank you for this example.

jfurnas’s picture

Sorry to reply to an old post, but this was helpful, mostly. One thing I noticed is that when you save an entity using a views selection handler, it doesn't appear to apply after save.

For example if you save an entity, the edit form shows the following format (content title (id)) in the field on edit, instead of what you originally put in (Content Title)

I am using this on a custom field so users type in a persons name based on a view, but when the entity is reloaded/edited, the user (uid) shows up in the box instead of what was originally typed in (User Name (id))

Any way to fix that?

daletrexel’s picture

Thank you! This is just what I was looking for (and surprised not to find in any official documentation).

rajeevgole’s picture

I have a content type ‘Article’ which has a checkbox field. Right now using the below code I am able to show all the nodes of the ‘article’ type.

$form['my_element'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',  
  '#selection_settings' => array(
    'target_bundles' => array('article'),
  ),
);

How can I restrict to only nodes of articles which have the checkbox checked?

robcarr’s picture

Can Views be referenced using this form element? I've tried (using '#target_type' => 'view',) and the filtering/selection works fine but the return value isn't a URL, but a string formatted as entity:node/VIEW_NAME instead