Skip to content

Instantly share code, notes, and snippets.

@WengerK
Last active May 4, 2023 19:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WengerK/cb48d935df6a5be245e141b6610eb58a to your computer and use it in GitHub Desktop.
Save WengerK/cb48d935df6a5be245e141b6610eb58a to your computer and use it in GitHub Desktop.
Article Ressources - How to create a custom Autocomplete using the Drupal 8 Form API

Article Ressources - How to create a custom Autocomplete using the Drupal 8 Form API

This is the Gist repository for my article How to create a custom Autocomplete using the Drupal 8 Form API.

Be aware that this article has been wrote for the Blog of Antistatique — Web Agency in Lausanne, Switzerland. A place where I work as Full Stack Web Developer.

Feel free to read it the full article on Medium or check it out on Antistatique.

Content of this gist :

  • ArticleAutocompleteForm.php : The form containing the autocomplete element.
  • ArticleAutoCompleteController.php : The controller which deal with buisness logic to populate autocomplete values.
  • my_module/my_module.routing.yml : The routing to expose the controller action.
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Entity\Element\EntityAutocomplete;
/**
* Defines a route controller for watches autocomplete form elements.
*/
class ArticleAutoCompleteController extends ControllerBase {
/**
* The node storage.
*
* @var \Drupal\node\NodeStorage
*/
protected $nodeStorage;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->nodeStorage = $entity_type_manager->getStorage('node');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
// Instantiates this form class.
return new static(
$container->get('entity_type.manager')
);
}
/**
* Handler for autocomplete request.
*/
public function handleAutocomplete(Request $request) {
$results = [];
$input = $request->query->get('q');
// Get the typed string from the URL, if it exists.
if (!$input) {
return new JsonResponse($results);
}
$input = Xss::filter($input);
$query = $this->nodeStorage->getQuery()
->condition('type', 'article')
->condition('title', $input, 'CONTAINS')
->groupBy('nid')
->sort('created', 'DESC')
->range(0, 10);
$ids = $query->execute();
$nodes = $ids ? $this->nodeStorage->loadMultiple($ids) : [];
foreach ($nodes as $node) {
switch ($node->isPublished()) {
case TRUE:
$availability = '✅';
break;
case FALSE:
default:
$availability = '🚫';
break;
}
$label = [
$node->getTitle(),
'<small>(' . $node->id() . ')</small>',
$availability,
];
$results[] = [
'value' => EntityAutocomplete::getEntityLabels([$node]),
'label' => implode(' ', $label),
];
}
return new JsonResponse($results);
}
}
<?php
namespace Drupal\my_module\Form;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Entity\Element\EntityAutocomplete;
/**
* Form to handle article autocomplete.
*/
class ArticleAutocompleteForm extends FormBase {
/**
* The node storage.
*
* @var \Drupal\node\NodeStorage
*/
protected $nodeStorage;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager) {
$this->nodeStorage = $entity_type_manager->getStorage('node');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.manager')
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['article'] = [
'#type' => 'textfield',
'#title' => $this->t('My Autocomplete'),
'#autocomplete_route_name' => 'my_module.autocomplete.articles',
];
$form['actions'] = ['#type' => 'actions'];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Save'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Extracts the entity ID from the autocompletion result.
$article_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($form_state->getValue('article'));
}
}
my_module.autocomplete.articles:
path: '/admin/my_module/autocomplete/articles'
defaults:
_controller: '\Drupal\my_module\Controller\ArticleAutoCompleteController::handleAutocomplete'
_format: json
requirements:
_permission: 'access content'
@aurelien-m
Copy link

Be careful with the spelling of nodeStorage in your file ArticleAutoCompleteController.php! Awesome article nevertheless :)

@WengerK
Copy link
Author

WengerK commented Apr 12, 2023

Be careful with the spelling of nodeStorage in your file ArticleAutoCompleteController.php! Awesome article nevertheless :)

thx <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment