Last updated July 12, 2012. Created by xenophyle on July 14, 2010.
Edited by aquadrop, hozzy, 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...
Comments
New callback
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
I can't get it to work!
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 =/
Solved it
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
You can check this :)
Click here : Test Autocomplete form
Regards,
Veera Prasad Dagudu
www.drup-all.com
Great Walkthrough
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
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
);
?>
Path should not start with search/...
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 ;)
The textfield needs an id.
I was seeing this error in firebug:
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',
);
?>
Thanks arnoldbird
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.
[Resolved]How to implement that in a block with various paths
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
www.pierdeipanema.com.br
www.facebook.com/pierdeipanema.net
I added a field radio with
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
www.pierdeipanema.com.br
www.facebook.com/pierdeipanema.net
An approach suggested by
An approach suggested by nevets:
'#states' => array('visible' => array(
':input[name="fieldname"]' => array('value' => 'option'),
),
),
Thanks!
Marco Telles
www.pierdeipanema.com.br
www.facebook.com/pierdeipanema.net
Just a little more detail please
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