Please Disable Your Browser Adblock Extension for our site and Refresh This Page!

our ads are user friendly, we do not serve popup ads. We serve responsible ads!

Refresh Page
Skip to main content
On . By CodimTh
Category:

in this tuto, I'll show you How to create a custom Autocomplete on text fields using the Drupal 8 Form API.

To use Autocomplete on text fields, just add property '#autocomplete_route_name' to a text field in a form. The route controller for this route must return an array of options for autocomplete, as a \Symfony\Component\HttpFoundation\JsonResponse object.

Step 1 - Define your module

create mymodule.info.yml file like this:

name: 'My Module'
description: 'My Module'
package: 'Custom'
type: module
core: 8.x 
core_version_requirement: ^8 || ^9

 

Step 2 - Define the routes

create mymodule.routing.yml file like this:

mymodule.autocomplete:
  path: '/autocomplete/articles'
  defaults:
    _controller: '\Drupal\mymodule\Controller\JsonApiArticlesController::handleAutocomplete'
    _format: json
  requirements:
    _permission: 'access content'

mymodule.form_autocomplete:
  path: '/autocomplete-form'
  defaults:
    _form:  '\Drupal\mymodule\Form\MyAutocompleteForm'
    _title: 'Autocomplete Form'
  requirements:
    _permission: 'access content'

 

Step 3 - Define The form and the fileds

create src/Form/MyAutocompleteForm.php file like this:

<?php

namespace Drupal\mymodule\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;

/**
 * Class MyAutocompleteForm
 * @package Drupal\mymodule\Form
 */
class MyAutocompleteForm extends FormBase
{

  /**
   * {@inheritdoc}
   */
  public function getFormId()
  {
    return 'my_autocomplete_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state)
  {
    $form['article'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Autocomplete Articles'),
      '#autocomplete_route_name' => 'mymodule.autocomplete',
    ];
    $form['actions'] = ['#type' => 'actions'];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save'),
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state)
  {
    $article_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($form_state->getValue('article'));
    \Drupal::messenger()->addMessage('Article ID is ' . $article_id);
  }


}

 

Step 4 - Add Controller and return JSON response

create src/Controller/JsonApiArticlesController.php file like this:

<?php

namespace Drupal\mymodule\Controller;

use Drupal\Core\Entity\Element\EntityAutocomplete;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\Xss;

/**
 * Class JsonApiArticlesController
 * @package Drupal\mymodule\Controller
 */
class JsonApiArticlesController
{

  /**
   * @return JsonResponse
   */
  public function handleAutocomplete(Request $request)
  {
    $results = [];
    $input = $request->query->get('q');
    if (!$input) {
      return new JsonResponse($results);
    }
    $input = Xss::filter($input);
    $query = \Drupal::entityQuery('node')
      ->condition('type', 'article')
      ->condition('title', $input, 'CONTAINS')
      ->groupBy('nid')
      ->sort('created', 'DESC')
      ->range(0, 10);
    $ids = $query->execute();
    $nodes = $ids ? \Drupal\node\Entity\Node::loadMultiple($ids) : [];
    foreach ($nodes as $node) {
      $results[] = [
        'value' => EntityAutocomplete::getEntityLabels([$node]),
        'label' => $node->getTitle().' ('.$node->id().')',
      ];
    }
    return new JsonResponse($results);
  }

}

 

And this is my final output:

custom autoComplete

 

If you want to select an entity, then there is a way easier way to do that. Drupal 8 has a standard entity_autocomplete field type, just specify your form element like this:

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.
  ),
);

 

Example:

 $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,


);

Comments

Add new comment

Restricted HTML

Search

Page Facebook

Become a patron

If you need some help or you search a Drupal freelancer don't hesitate to contact us.

 

Contact Us

All the content is FREE but I still need your help

 

Become a patreon