Add ajax multiple autocomplete to textarea

In this article we will show a solution to add an ajax call to populate multiple information in a Drupal 8 form textarea element.

In this example, the script will autocomplete users list in the form for a custom module called MyModule. The user will enter first 2 letters of a name or email.

1) create a library

In MyModule.libraries.yml add the necessary javascript reference that will be used to populate the users in the form:

MyModule_lib:
  version: VERSION
  js:
    js/autocomplete.js: {}
  dependencies:
    - core/jquery
    - core/jquery.ui.autocomplete

The autocomplete function as dependencies which are based on jQuery library.

 

2) JS script

The jQuery autocomplete.js file that we use is copied below. It is implemented as Drupal behaviors You need to add this file in MyModule/js/ folder.
 

JS script:

(function ($, Drupal, drupalSettings) {

  Drupal.behaviors.MyModule_autocomplete = {
    attach: function (context, settings) {
         
    
      jQuery(function() {
        
        function split( val ) {
          return val.split( /,\s*/
          );
          }

        function extractLast( term ) {
          return split( term ).pop();
          }
          jQuery( "#edit-users" )
          .bind( "keydown", function( event ) {
            if ( event.keyCode === jQuery.ui.keyCode.TAB &&
            jQuery( this ).data( "ui-autocomplete" ).menu.active ) {
              event.preventDefault();
            }
          })
          .autocomplete({
            source: function( request, response ) {
              jQuery.getJSON("mypath/autocomplete", {
              term: extractLast( request.term )
              }, response );
            },
            search: function() {
              // custom minLength
              var term = extractLast( this.value );
                if ( term.length < 2 ) {
                  return false;
                }
            },
            focus: function() {
              // prevent value inserted on focus
              return false;
            },
            select: function( event, ui ) {
              var terms = split( this.value );
              // remove the current input
                terms.pop();
              // add the selected item
                terms.push( ui.item.value );
              // add placeholder to get the comma-and-space at the end - used for multi select
                terms.push( "" );
                this.value = terms.join( ", " );
              
              return false;
            }
        });
      });
    }
  };
})(jQuery, Drupal, drupalSettings);

 

3) Route

In the script above, the "path/autocomplete" is the path to the controller function that will handle and return the queries.

In your file "MyModule.routing.yml", you need to have a route to the function like:

form_autocomplete:
  path: '/mypath/autocomplete'
  defaults:
    _controller: '\Drupal\MyModule\Controller\MyController::autocomplete'

4) Controller

In MyController class, the autocomplete function will return the list of names that will be populated in the form textbox:

public function autocomplete(Request $request) {

        $text = $request->query->get('term');

        $query = "SELECT distinct name from {users_field_data} WHERE mail like :t1 or name like :t2 ";
        $a = array(':t1' => "$text%", ':t2' => "$text%");
        $name = db_query($query, $a)->fetchCol();

        return new JsonResponse($name);
    }

In the function above the 'term' is the user input. The script will query the database for users names or users emails that match the input and will return it as a Json array.

5) The form

In the custom module form, add the textarea element:

    $form['users'] = array(
      '#type' => 'textarea',
      '#rows' => 2,
      '#attributes' => array('placeholder' => t('enter recipients name separated by comma.')),
      '#required' => TRUE,
      '#default_value' => NULL,

6) the result

The result will show as below. When the user type first 2 letters of the name he is looking for, a list of matches will be displayed below the box and added to the list in the textarea when clicked. The values of the list are separated by a comma (see the terms.join( ", " ) function in autocomplete.js).

autocomplete textarea

 

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.