Change entity autocomplete selection rules in Drupal 8
I've prepared a particular topic for Drupal enthusiasts and passionate community members. It's about the Drupal 8 trick that can make your coding life more comfortable.
Drupal 8 contains a new form element called entity_autocomplete. For example, this code shows an essential autocomplete element that matches node titles from all bundles:
$form['my_element'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
// #default_value - Entity object or an array of entity objects.
'#default_value' => $entity,
];
The entity type is required in #target_type. 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'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
'#selection_settings' => [
'target_bundles' => ['article', 'page'],
],
];
#selection_settings – an array of settings passed to the selection handler.
If we want to allow 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'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
'#tags' => TRUE,
];
In some cases, we need to use specific selection rules for autocomplete results. And, in this case, #selection_handler param can help. The default selection handler is pre-populated to 'default'. You can set here a plugin ID of the entity reference selection handler.
For example, we want to get results filtered by value from the node field. That's how it should look:
$form['my_element'] = [
'#type' => 'entity_autocomplete',
'#target_type' => 'node',
'#selection_handler' => 'default:node_by_field',
'#selection_settings' => [
'target_bundles' => ['article'],
'filter' => ['field_dummy_filter' => $dummy_field_value],
],
];
Where:
- default:node_by_field – custom selection handler
- filter – param that used in custom selection handler.
For default:node_by_field custom selection handler we need to create EntityReferenceSelection plugin extended from NodeSelection class:
<?php
namespace Drupal\test_module_name\Plugin\EntityReferenceSelection;
use Drupal\node\Plugin\EntityReferenceSelection\NodeSelection;
/**
* Provides specific access control for the node entity type.
*
* @EntityReferenceSelection(
* id = "default:node_by_field",
* label = @Translation("Node by field selection"),
* entity_types = {"node"},
* group = "default",
* weight = 3
* )
*/
class NodeByFieldSelection extends NodeSelection {
/**
* {@inheritdoc}
*/
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
$query = parent::buildEntityQuery($match, $match_operator);
$handler_settings = $this->configuration['handler_settings'];
if (!isset($handler_settings['filter'])) {
return $query;
}
$filter_settings = $handler_settings['filter'];
foreach ($filter_settings as $field_name => $value) {
$query->condition($field_name, $value, '=');
}
return $query;
}
}
As a result, entity_autocomplete will show only nodes that meet the additional condition.
LET'S CONNECT
Get a stunning website, integrate with your tools,
measure, optimize and focus on success!