How To Create an Ajax Autocomplete Textfield In Drupal 7

People are lazy by nature and love when something is done for them automatically. As web developers, we can always use this need in our website designs by creating different autocomplete fields to ease website visitor's experience. Being the best CMS platform outhere, Drupal allows us to create autocomplete fields within a blink of an eye. Here’s how to do this:

Let’s imagine, you’re building some form where you want to help user with an autocomplete. For example, this can be a "City" input textfield. You can have something similar to the following form:

function module_name_form() {
  $form = array();
 
  $form['city'] = array(
    '#title' => t('City'),
    '#type' => 'textfield',
    '#autocomplete_path' => 'example/autocomplete',
   );
 
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save',
  );
 
  return $form;
}

The most interesting part here is: '#autocomplete_path' => 'example/autocomplete' which defines an autocomplete callback for our textfield. When user types something into our textfield, Drupal sends a request via this url to send data you input and to receive suggestions via json if there are any. To make Drupal aware of this path, let’s add it to the menu system:

function module_name_menu() {  
  $items['example/autocomplete'] = array(
    'page callback' => '_module_name_autocomplete',
    'access arguments' => array('access example autocomplete'),
    'type' => MENU_CALLBACK
  );
  return $items;
}

The last step is to create a _module_name_autocomplete function which will look for a suggestion and return it to the user.

function _module_name_autocomplete($string) {
  $matches = array();
 
  // Some fantasy DB table which holds cities
  $query = db_select('cities', 'c');
 
  // Select rows that match the string
  $return = $query
    ->fields('c', array('city'))
    ->condition('c.city', '%' . db_like($string) . '%', 'LIKE')
    ->range(0, 10)
    ->execute();
 
  // add matches to $matches  
  foreach ($return as $row) {
    $matches[$row->city] = check_plain($row->city);
  }
 
  // return for JS
  drupal_json_output($matches);
}

In this function we query DB to find a match for a string typed in by a user. I use Dynamic queries (http://drupal.org/node/310075) to get data from a DB, if you feel yourself more comfortable with a SQL approach, feel free to use it as well. The current query is a fantasy one, yours can be a very different from this. If you want for a more advanced example, look in to the Drupal’s core taxonomy autocomplete function which can be found in ‘modules/taxonomy/taxonomy.pages.inc’, line 79: function taxonomy_autocomplete.

All in all, I guess now you have an idea about hot to create an autocomplete text field in your custom Drupal 7 module.

Happy Drupal Coding!

Comments

Submitted by Kelly on Sun, 2012-01-08 05:06

Finally...Thanks for sharing. I have been looking for sometime on how to make an autocomplete field in Drupal 7 using the database api. I have found a ton of examples, but yours was the only one that was using the "propper" db api way. Should be on the Docs page at drupal.org.

Submitted by Anderson on Wed, 2014-08-27 09:03

Here are update Drupal documentation, to create an Ajax Autocomplete Textfield in Drupal 7 http://drupal.org/node/854216

Submitted by Kelly on Sun, 2012-01-08 06:12

Since there was a hole in the Drupal documentation, I adapted this to drupal.org and attributed this page, please check out http://drupal.org/node/854216 for more info.

Submitted by SomethingOn on Thu, 2012-01-19 06:24

I followed your code for a hook_form_alter and it worked perfectly, BUT when I tried adding the code to a custom module (block with a form in it) the form shows up but the auto-complete isn't working. Looks like the autocomplete JS library isn't there.

Is there something I have to tell Drupal in my_modue_init or something to make sure it loads the necessary libraries?

Submitted by Tim on Thu, 2012-01-19 10:25

Actually everything should be just fine. Make sure you have all functions I mentioned in my example. Make sure that autocomplete path is registered with hook_menu and callback function returns drupal_json_output($matches).

Submitted by Vadim on Fri, 2012-02-17 16:17

On a simple page it work great, but what to do in the case if I output a page in a modal window using fancybox ?

Submitted by kkatusic on Wed, 2012-02-29 15:29

Nice tuts, but how can I append new city, not replace?

Thx

Submitted by ryan on Fri, 2012-03-02 23:18

Not working for me. In firebug I'm seeing...
uncaught exception: Syntax error, unrecognized expression: #

Submitted by ryan on Fri, 2012-03-02 23:38

re: the problem I reported here a few minutes ago, I posted a solution/workaround at http://drupal.org/node/854216#comment-5681368

No doubt it's not a problem with the code on this page. Perhaps a bug in Drupal. Not sure.

Submitted by baobao on Fri, 2012-04-20 06:05

Thanks :)

Submitted by Jayaram on Tue, 2012-05-01 21:50

How do i filter autocomplete results based on content type? I want the user to select the filter type.

Submitted by Michael on Sun, 2012-12-30 02:24

This is how I have adapted it for my code. Simply add another condition that filters for the content type you are after.

$return = $query
->fields('n', array('title'))
->condition('n.type', YOUR_CONTENT_TYPE)
// the title must start with the $string
->condition('n.title', db_like($string) . '%', 'LIKE')
->orderBy('title')
->range(0, 10)
->execute();

Submitted by Marco on Wed, 2012-06-06 15:10

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.

Submitted by stomerfull on Thu, 2012-11-15 16:00

Hello ,

Not able to get autocomplete working where user is not logging (anonymous)

Thanks in advance for your help

Submitted by Ruchira on Mon, 2013-03-11 11:56

Wan to know how to use that form.
Thanks

Submitted by wilzonm on Fri, 2013-03-15 04:23

as show where show, example please?

Submitted by monika kadam on Fri, 2013-05-24 15:29

Thank's your code works perfectly fine....
:-)

Submitted by Garik on Tue, 2013-07-09 21:13

Thanks for the recipe! Tell me, please, how to pass an additional argument to the _module_name_autocomplete? For example, to restrict the search for the terms of taxonomy I want to pass to the function vid of vocabulary.

Submitted by Mac0s on Tue, 2013-08-27 11:38

return drupal_json_output(drupal_map_assoc(db_select('cities', 'c')
		->fields('c', array('city'))
		->condition('c.city', '%' . db_like($string) . '%', 'LIKE')
		->range(0, 10)
		->execute()
		->fetchCol()));

not correct:
->condition('c.city', '%' . db_like($string) . '%', 'LIKE')
correct:
->condition('c.city',db_like($string) . '%', 'LIKE')

Submitted by Tim on Fri, 2013-08-30 10:45

why?

Submitted by localh3 on Tue, 2014-11-25 16:01

both ways are correct.
It is just like using "%[some value]%" is regular sql.

Add new comment

You are here