#autocomplete_path in textfield elements

CMS Blog image

Sometimes in the web development process, the need arises to create an autocomplete field in order to enhance usability. As worked examples of such fields, widgets for cck-fields Node reference and User reference can be mentioned.

Let's look at some attempts of program creation of such fields. According to Drupal Forms API reference #autocomplete_path function can be added only for text field element. This feature will identify the path through which Drupal JavaScript-code that is automatically turned on will send HTTP-requests, using JQuery.

First of all, we'll announce text field in the form:

php
$form['example'] = array(
'#type' => 'textfield',
'#title' => t('Example Textfield'),
'#autocomplete_path' => 'products/autocomplete',
);

Now we'll identify callback for autocomplete in hook_menu():

php
/**
* Implementation of hook_menu
*/
function module_menu() {
$items['products/autocomplete'] = array(
'page callback' => 'module_products_autocomplete',
'type' => MENU_CALLBACK,
'access arguments' => array('administer nodes'),
);

return $items;
}

Finally, we must describe callback function itself that will transfer some array of drupal_json() function:

php
function module_products_autocomplete($string) {
$matches = array();
$res = db_query("SELECT title, nid FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%')", $string);

while ($row = db_fetch_array($res)) {
$matches[$row['nid']] = $row['title'];
}
drupal_json($matches);
}

Now we have a full-blown autocomplete field.

Quite often, though, there is a need to pass some parameters of the autocomplete function. In my case, there was a need to pass an array of node identifications and to limit the scope of nodes to only this array in autocomplete. For this reason, we'll identify page arguments in hook_menu() for that:

php

/**
* Implementation of hook_menu
*/
function module_menu() {
$items['products/autocomplete/%'] = array(
'page callback' => 'module_products_autocomplete',
'page arguments' => array(2),
'type' => MENU_CALLBACK,
'access arguments' => array('administer nodes'),
);

return $items;
}

Let's make some amendments in the autocomplete_path settings for text field definition:

php
//we get $nids array with identificators of nodes
$string_nids = implode('|', $nids);
$form['example'] = array(
'#type' => 'textfield',
'#title' => t('Example Textfield'),
'#autocomplete_path' => "products/autocomplete/{$string_nids}",
);

$string parameter is being automatically passed to autocomplete function with the help of API. If you want to pass additional parameters, place them before $string:

php
function module_products_autocomplete($arg2, $string) {
$matches = array();
$nids = explode('|', $arg2);
$res = db_query("SELECT title, nid FROM {node} WHERE LOWER(title) LIKE LOWER('%s%%') AND nid IN (" . db_placeholders($nids, 'int') . ")", array_merge(array($string), $nids));

while ($row = db_fetch_array($res)) {
$matches[$row['nid']] = $row['title'];
}
drupal_json($matches);
}

Drupal will visualize all above-mentioned the following way: