Last updated July 12, 2012. Created by xenophyle on July 14, 2010.
Edited by aquadrop, hayskelly, moestavern. Log in to edit this page.

Autocomplete is implemented in Drupal through AJAX. When users type into a textbox, code on the client page dynamically loads new data from the server (a Drupal website) and uses this data to update the user display (provide a drop-down list of matching options, which the user can select from).

Handily, all the mechanics of exchanging data between client and server and of updating the display are handled by the widget, autocomplete.js. Implementing a particular autocomplete textfield requires two parts: (a) a caller (the textfield, with special additions) and (b) a handler, which is a PHP function that parses the request and returns a response.

Prebuilt autocomplete functions

Two autocomplete functions ship with the Drupal core. Each is referenced by an "autocomplete_path"--the uri to which autocomplete requests are sent.

* user_autocomplete()
Use this function to load matching user names. Autocomplete path: user/autocomplete.
* taxonomy_autocomplete()
Use this function to load matching taxonomy terms from a given vocabulary. Autocomplete path: taxonomy/autocomplete.

If one of these matches your needs, then all you need to do is include the special #autocomplete_path selector in a form field. Here's an example for user autocomplete (from comment.module):

<?php
        $form
['admin']['author'] = array(
         
'#type' => 'textfield',
         
'#title' => t('Authored by'),
         
'#size' => 30,
         
'#maxlength' => 60,
         
'#autocomplete_path' => 'user/autocomplete',
         
'#default_value' => $author,
         
'#weight' => -1,
        );
?>

For taxonomy autocomplete, include a vocabulary id, as in this example from taxonomy.module:

<?php
        $form
['taxonomy']['tags'][$vocabulary->vid] = array('#type' => 'textfield',
         
'#title' => $vocabulary->name,
         
'#description' => $help,
         
'#required' => $vocabulary->required,
         
'#default_value' => $typed_string,
         
'#autocomplete_path' => 'taxonomy/autocomplete/'. $vocabulary->vid,
         
'#weight' => $vocabulary->weight,
         
'#maxlength' => 1024,
        );
?>

Building a custom autocomplete function

If you want to make your own autocomplete function to answer a need not already met, there are a couple of additional steps.

The form

The form will contain an element such as

<?php
  $form
['city'] = array(
   
'#type' => 'textfield',
   
'#title' => 'City',
   
'#maxlength' => 128,
   
'#autocomplete_path' => 'cities/autocomplete',
  );
?>

Addition to hook_menu

You must add #autocomplete_path to your hook_menu function.

<?php
   
function cities_menu(){
    ...
   
// path with autocomplete function for cities
   
$items['cities/autocomplete'] = array(
     
'title' => 'Autocomplete for cities',
     
'page callback' => '_cities_autocomplete',
     
'access arguments' => array('use autocomplete'),  //or whatever permission makes sense
     
'type' => MENU_CALLBACK
   
);
    return
$items;
?>

Make a call to the Database, D6 Version

Write the handler function. This will receive an autocomplete request and return data to the client in a form ready to be parsed by automplete.js.

<?php
/**
* autocomplete helper
* $string = string for search
*/
function _cities_autocomplete($string) {
 
$matches = array();
 
//search table `cities` for cities that begin with the letters the user enters in the form
 
$result = db_query_range("SELECT city FROM {cities} WHERE LOWER(city) LIKE LOWER('%s%')", $string, 0, 10);
 
// add matches to $matches
 
while ($data = db_fetch_object($result)) {
   
$matches[$data->city] = check_plain($data->city);
  }
 
// return for JS
 
print drupal_to_js($matches);
  exit();
}
?>

Note that you are (a) finding matching records based on user input (b) constructing an array of matches (c) converting the array to JavaScript code and (d) outputting the results.

Also note that we need to escape the city name in the $matches array's values: this is because the values are HTML. Not escaping would open up XSS holes. On the other hand, it also means that you can mark-up the autocomplete suggestions any way you like.

Make a call to the Database, D7 Version

If you on Drupal 7, and want to use the Database API, your code would look slightly different.

<?php
/**
* autocomplete helper
* $string = string for search
*/
function _cities_autocomplete($string) {
 
$matches = array();
 
$result = db_select('cities', 'c')
    ->
fields('c', array('city'))
    ->
condition('city', '%' . db_like($string) . '%', 'LIKE')
    ->
execute();
 
// save the query to matches
 
foreach ($result as $row) {
   
$matches[$row->city] = check_plain($row->city);
  }
 
// Return the result to the form in json
 
drupal_json_output($matches);
}
?>

Security note:

Make sure your autocomplete handler has appropriate menu permissions set on it, and respects existing access control mechanisms. Otherwise, you might be exposing sensitive information through the autocomplete.

Adapted from http://drupal.org/node/208424#comment-686252, http://drupal.org/node/42552 and http://timonweb.com/how-create-ajax-autocomplete-textfield-drupal-7

Additional example for D6: http://digitalillusion.altervista.org/wordpress/2009/01/12/drupal-6-link...

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

I've replaced:
print drupal_to_js($matches);
exit();

with:
drupal_json($matches);

with good results.

Reference: http://drupal.org/update/modules/6/7#rename-drupal-to-js

This is driving me nuts. I've tried to make a custom autocomplete function as described above. Did not work. Then I copy and pasted the whole code (of course I put it into the appropriate functions). I created a table 'cities' with several entries for 'city'. Did not work.

When I use user/autocomplete, it's working fine. If I change it to cities/autocomplete then I don't get the small autocomplete circle or anything.

It simply won't work.

Am I stupid or is there something wrong with the code? Please help, I'm slowly despairing =/

Wow, after slaving for hours I find the solution a couple of minutes after I comment here.

The code above does indeed need changing. The code that belong into the hook_menu requires a 'return $items;' at the end. The author of the above tutorial probably overlooked this.

edit: I amended the code in the tutorial accordingly

Regards,
Veera Prasad Dagudu
www.drup-all.com

I was hitting a wall about autocomplete and how I couldn't get mine to work.
Then, I found the small glitch.

This didn't work:

$form['account_sync_fields_map']['sync_'.$map_id]['remote'] = array(
  '#type' => 'textfield',
          '#default_value' => $details['remote'],
          '#autocomplete_path' => '/admin/account_sync/autocomplete',
          '#maxlength' => 1024,
        );

This did:

$form['account_sync_fields_map']['sync_'.$map_id]['remote'] = array(
  '#type' => 'textfield',
          '#default_value' => $details['remote'],
          '#autocomplete_path' => 'admin/account_sync/autocomplete',
          '#maxlength' => 1024,
        );

The difference is that the path had to not have a leading slash.

13 years of Content Management - 6 years of Drupal experience
Our company: http://www.thosedewolfes.com/ - http://twitter.com/#!/thosedewolfes
My site: http://mike.dewolfe.bc.ca/ - http://twitter.com/#!/dewolfe001

For Drupal 7 code is something like this.
where field_tags is taxonomy field in node with widget type autocomplete.

<?php
   $node
=node_load($nid);
   
$tags = array();
    foreach (
$node->field_tags['und'] as $item) {
     
$tags[$item['tid']] = isset($item['taxonomy_term']) ? $item['taxonomy_term'] : taxonomy_term_load($item['tid']);
    }
   
$form['tags'] = array(
     
'#type' => 'textfield',
     
'#default_value' => taxonomy_implode_tags($tags),
     
'#title' => 'Add Tags',
     
'#autocomplete_path' => 'taxonomy/autocomplete/field_tags',
     
'#maxlength' => 1024,
     
'#element_validate' => array('taxonomy_autocomplete_validate'),page
       
);
?>

Do not start your Path with search as in "search/yourlistpath". This will not work because it triggers a Search. Obvious only to those who know ;)

I was seeing this error in firebug:

uncaught exception: Syntax error, unrecognized expression: #

I also saw a notice in Drupal referencing line 3707 of forms.inc. This is in Drupal 7.12.

If I add an id to the city field in hook_form, the errors go away...

<?php
  $form
['city'] = array(
   
'#id' => 'something-unique',
   
'#type' => 'textfield',
   
'#title' => 'City',
   
'#maxlength' => 128,
   
'#autocomplete_path' => 'cities/autocomplete',
  );
?>

I was having trouble with this for hours. All of the tutorials I encountered have very specific syntax, which I followed.

My autocomplete fields would not get any results until I read this and added the unique ID.

<?php
function user_autocomplete_menu() {
 
$items['user_autocomplete'] = array(
   
'title' => 'User Autocomplete',
   
'page callback' => 'user_autocomplete_page',
   
'access arguments' => array('access content'),
   );
$items['demo-autocomplete-engine'] = array(
   
'page callback' => 'demo_autocomplete',
   
'access arguments' => array('view published content'),
   
'type' => MENU_CALLBACK,
  );
  return
$items;
}
function
user_autocomplete_page () {
    return
drupal_get_form('user_form');
}
function
user_form($form, &$form_state) {
   
$form = array();
   
$form['user'] = array (
       
'#type'        =>    'textfield',
       
'#title'    =>    t('Test autocomplete '),
       
'#required' =>     TRUE,
       
'#autocomplete_path' => 'user/autocomplete',
    );
      
$form['codes'] = array(
   
'#title' => t('Codes'),
   
'#type' => 'textfield',
   
'#maxlength' => 60,
   
'#autocomplete_path' => 'demo-autocomplete-engine',
);
     return
$form;
  }
function
demo_autocomplete($string = '') {
 
$matches = array();
  if (
$string) {
   
$result = db_select('voucher')->fields('voucher', array('promo_code'))->condition('promo_code', db_like($string) . '%', 'LIKE')->range(0, 10)->execute();
    foreach (
$result as $user) {
     
$matches[$user->promo_code] = check_plain($user->promo_code);
    }
  }
 
drupal_json_output($matches);
}
?>

Thanks arnoldbird!!! I had the same issue with

uncaught exception: Syntax error, unrecognized expression: #

and adding the '#id' parameter solved it. ...using Drupal 7.23

Thanks!
Your code for autocomplete textfield worked perfectly, but how to implement that in a block ?
A block is published in various paths...

Best regards.

Marco Telles
Amazon Cloud Professional
pierdeipanema.com.br

I added a field radio with two options: "user" or "title".
When this field is selected, the autocomplete should display its content.
How to do this?
Thanks

Marco Telles
Amazon Cloud Professional
pierdeipanema.com.br

An approach suggested by nevets:

        '#states' => array(
          'visible' => array(
            ':input[name="fieldname"]' => array('value' => 'option'),
          ),
        ),

Thanks!

Marco Telles
Amazon Cloud Professional
pierdeipanema.com.br

I am a recent convert from DotNetNuke to Drupal. So I would really appreciate some more help with this feature.

I have 2 questions -

1. $form['city'] = array(... Does this portion add a text box? I already have a text box in my code for the "Content". How can I adapt this to that textbox (input)?

2. Do the addition to hook_menu and the callback function go in system.api.php? Or should I be adding it somewhere else?

Thank you for your replies
Sai