Enable AJAX autocomplete on a Drupal 7 Webform textfield

ArticleMay 20, 2011

This tutorial demonstrates how to implement Drupal's native AJAX autocomplete widget on a Webform textfield.

To follow along you will need a working copy of Drupal 7, the Webform module, a published webform with a textfield named 'node', and some dummy node content. This tutorial was authored using Drupal 7.0 and Webform 7.x-3.11.

To accomplish this task we're going to write a custom module named Demo that consists of two files: demo.info and demo.module. Both demo.info and demo.module reside in a folder apropriately named demo that I've placed in sites/default/modules to help differentiate it from contributed modules (like Webform).

Here's the finished code, but read on if you'd like a more detailed explanation of the functionality involved.

demo.info

name = Demo 
description = Enables Drupal core AJAX autocomplete widget for a Webform textfield. 
core = 7.x 
package = Webform 
dependencies[] = webform 
files[] = demo.module

demo.module


/**
 * Implements hook_form_alter().
 */
function demo_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'webform_client_form_1') {
   //add autocomplete handler for properties 
    $form['submitted']['node']['#autocomplete_path'] = 'node/autocomplete';
  }
}
/**
 * Implements hook_menu().
 */
function demo_menu() {
  $items = array();
  $items['node/autocomplete'] = array( 'title' => 'Node autocomplete', 'page callback' => 'node_autocomplete', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items;
}
/**
 * Retrieve a JSON object containing autocomplete suggestions for node titles.
 */
function node_autocomplete($string = '') {
  $matches = array(); $result = db_select('node') ->fields('node', array('title')) ->range(0, 20) ->execute(); foreach ($result as $node) { $matches[$node->title] = check_plain($node->title); } drupal_json_output($matches);
} 

Now we'll break down the different steps involved in accomplishing our task.

demo.info

name = Demo 
description = Enables Drupal core AJAX autocomplete widget for a Webform textfield.
 core = 7.x 
package = Webform 
dependencies[] = webform 
files[] = demo.module 

To begin, we have our demo.info file that tells Drupal a little about our custom module. It's pretty self-explanatory, and the only thing to note is that it declares Webform as a dependency. This means that Drupal won't allow you to enable this custom module without Webform being enabled as well.

With the .info file out of the way, we can get on to the fun stuff.

demo.module

/** 
* Implements hook_form_alter().
*/
 function demo_form_alter(&$form, &$form_state, $form_id) { 
  if ($form_id == 'webform_client_form_1') { 
  //add autocomplete handler for properties 
 $form['submitted']['node']['#autocomplete_path'] = 'node/autocomplete'; 
 }
} 

The preceding code block implements hook_form_alter() so that we can add the #autocomplete_path attribute to our form field. The attribute specifies the path that the autocomplete script will execute against to generate the sourcedata for the autocomplete widget.

demo.module

/** 
* Implements hook_menu(). 
*/
 function demo_menu() { 
  $items = array(); 
  $items['node/autocomplete'] = array( 'title' => 'Node autocomplete', 'page callback' => 'node_autocomplete', 'access callback' => 'user_access', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); 
  return $items;
 } 

The preceding code block implements hook_menu() and declares a callback function (node_autocomplete) for any requests for the properties/autocomplete path (declared in demo_form_alter() above).

demo.module

/** 
* Retrieve a JSON object containing autocomplete suggestions for node titles. 
*/
 function node_autocomplete($string = '') {
   $matches = array(); 
   $result = db_select('node') ->fields('node', array('title')) ->range(0, 20) ->execute(); 
   foreach ($result as $node) { 
     $matches[$node->title] = check_plain($node->title); 
    } 
    drupal_json_output($matches); 
} 

The final function in our module queries our database and returns 20 node titles. The autocomplete widget uses JavaScript, so after the $matches array has been populated we then convert the output to json and presto!

By default, the Drupal 7 core provides the necessary functionality to implement the autocomplete widget for users and taxonomy (Hint: search the Drupal 7 core for '#autocomplete_path'). With that in mind, outside of a quick hook_form_alter all I needed to do was appropriate the existing code and then tweak it to my needs.

That wraps up this tutorial and I hope you enjoyed it. Comments, questions and critiques are always welcome in the comments section below.