Custom Autocomplete Path on CCK Node Reference Fields

Posted on Sept. 3, 2012, 1:59 p.m.

In a recent post, I explained how to dynamically alter the AJAX behavior of an autocomplete field in Drupal. But what if you have the similar node reference field, and want to modify the result set? This post will show you how.

Let's go over some assumptions:

  1. For simplicity, we will alter the field to show only nodes in English.
  2. This will only alter the autocomplete behavior, not the validation. If your field is set to accept a limited set of nodes, the suggestions have to be a subset. Altering the validation of the field is a post for another - longer - day.
  3. Our field's machine name is field_reference.
  4. Our field is set to accept only 1 value.

First, let's add the menu hook and the autocomplete behavior. Fairly standard stuff:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
/**                                                                           
 * Implements hook_form_alter().                                              
 */                                                                           
function example_module_menu() {                                              
  $items = array();                                                           
  $items['example_autocomplete'] = array(                                     
    'type' => MENU_CALLBACK,                                                  
    'page callback' => 'example_module_autocomplete',                         
    'access callback' => TRUE,                                                      );                                                                          
  return $items;                                                              
}

function example_module_autocomplete($input) {                                
  $results = array();                                                         
  $resource = db_query_range("SELECT nid, title FROM {node} WHERE language = '%s' AND title LIKE '%s%%'", 'en', $input, 0, 10);

  while ($node = db_fetch_object($resource)) {                                
    $key = sprintf('%s [nid: %d]', $node->title, $node->nid);                 
    $results[$key] = $node->title;                                            
  }                                                                           
  print json_encode($results);                                                
  exit();                                                                     
}

As you can see, all we're doing is providing a new AJAX callback. In that callback, we select nodes from the database and limit them by language. Now, let's define our form alter hook. But remember, like all CCK fields, hook_form_alter is too early in the process to modify a field. So instead, we define an #after_build function that will get called further down the road. Like so:

1
2
3
4
5
6
7
8
9
<?php
/**                                                                           
 * Implements hook_form_alter().                                                   
 */                                                                               
function example_module_form_alter(&$form, &$form_state, $form_id) {          
  if ($form_id == 'post_node_form') {                                         
    $form['#after_build'][] = 'example_module_after_build';                   
  }                                                                           
}

Finally, we'll actually alter the form field in our #after_build function. If you're alter a field set to multiple values, be sure to loop over the field and alter all rows.

1
2
3
4
5
<?php
function example_module_after_build($form, &$form_state) {                    
  $form['field_reference'][0]['nid']['nid']['#autocomplete_path'] = 'example_autocomplete';
  return $form;                                                               
}

Learning Drupal? Subscribe to my Drupal articles, tips and tutorials.