Home Drupal Drupal custom form with autocomplete drop down
formats

Drupal custom form with autocomplete drop down

Published on April 2, 2011 by in Drupal, PHP

I had been putting off doing an custom autocomplete programmatically in drupal for a long time. I finally sat down and decided to work it out for a project i was doing. It was surprisingly very easy. My project consisted of pulling an autocomplete text field from a taxonomy list.

The first step is to build your menu callbacks via hook_menu api. For those not as familiar with drupal what a menu call back does is setup a path or route that when entered in a url executes a function.

The first menu item is to setup the form. The page callback calls drupal_get_form and we are passing the defined search form to that callback.

The second menu item is the autocomplete query callback. This is where the actual query is performed that returns the list of categories.

//Hook Menu items:
function mymodule_menu() { 
  $items['searchform'] = array(
          'page callback' => 'drupal_get_form',
          'page arguments' => array('mymodule_form'),
          'access arguments' => array('access content'),
          'type' => MENU_CALLBACK,
          ); 

$items['category/autocomplete'] = array(      
      'title' => 'Autocomplete for categories',
      'page callback' => '_category_autocomplete',
      'access callback' =>TRUE,
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
    );
}

The Next step is to define your form using hook_form api. This is where we attach the autocomplete callback, for when you type in the text field it performs the query, and returns the data. The key parameter field is the #autocomplete_path entry in the form elements. This path is the menu callback path we defines above in the hook_menu section of the code.

 

//hook form 
 function mymodule_form(&$form_state = NULL){
     // drupal_add_js('sites/all/misc/autocomplete.js', 'theme', 'header');
     // Added custom overide for drupals built in autocomplete.js 
     // this allowed me to overide some of the internal autocomplete settings.
     // You can remove the drupal_add_js  line for default values in your autocomplete
    $form = array();      
    $form['category'] = array(
    '#type' => 'textfield',
    '#title' => 'Category',
    '#maxlength' => 128,
    '#autocomplete_path' => 'category/autocomplete',
  );

      // add a submit button
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );

  // return form array
  return $form;   
     }

The final step is to create your query and pass the data back to your form. Note this can be any type of query you like, I used views to build the queury I needed and I copied that for the code below. The drupal_to_js basically returns a JSON array back to the form. If you are using Drupal 7 you will need to change this to drupal_json_encode instead.

 
//Autocomplete queries:

function _category_autocomplete($string) {
  $matches = array();
  // searching in database, only city column
  $result = db_query_range("SELECT term_data.tid AS tid,
   term_data.name AS term_data_name,
   term_data.vid AS term_data_vid
 FROM term_data term_data 
 WHERE LOWER(term_data.name) LIKE LOWER('%s%%') and term_data.vid in ('2')
   ORDER BY term_data_name ASC", $string, 0, 10);
  // found wrote into $matches
  while ($data = db_fetch_object($result)) {
    $matches[$data->term_data_name] = check_plain($data->term_data_name);
  }
  // return for JS
  print drupal_to_js($matches);
  // for drupal 7 comment out drupal_to_js and uncomment below
  //drupal_json_encode($matches);

  // we don't need goto next PHP
  exit();
}

I have not tested this under drupal 7 yet, but with a few minor changes like I notated above, it should work.

Here is the complete code below:

 
//Hook Menu items:
function mymodule_menu() { 
  $items['searchform'] = array(
          'page callback' => 'drupal_get_form',
          'page arguments' => array('mymodule_form'),
          'access arguments' => array('access content'),
          'type' => MENU_CALLBACK,
          ); 

$items['category/autocomplete'] = array(      
      'title' => 'Autocomplete for categories',
      'page callback' => '_category_autocomplete',
      'access callback' =>TRUE,
      'access arguments' => array('access content'),
      'type' => MENU_CALLBACK
    );
}

//hook form 
 function mymodule_form(&$form_state = NULL){
     // drupal_add_js('sites/all/misc/autocomplete.js', 'theme', 'header');
     // Added custom overide for drupals built in autocomplete.js 
     // this allowed me to overide some of the internal autocomplete settings.
     // You can remove the drupal_add_js  line for default values in your autocomplete
    $form = array();      
    $form['category'] = array(
    '#type' => 'textfield',
    '#title' => 'Category',
    '#maxlength' => 128,
    '#autocomplete_path' => 'category/autocomplete',
  );

      // add a submit button
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );

  // return form array
  return $form;   
     } 

//Autocomplete queries:

function _category_autocomplete($string) {
  $matches = array();
  // searching in database, only city column
  $result = db_query_range("SELECT term_data.tid AS tid,
   term_data.name AS term_data_name,
   term_data.vid AS term_data_vid
 FROM term_data term_data 
 WHERE LOWER(term_data.name) LIKE LOWER('%s%%') and term_data.vid in ('2')
   ORDER BY term_data_name ASC", $string, 0, 10);
  // found wrote into $matches
  while ($data = db_fetch_object($result)) {
    $matches[$data->term_data_name] = check_plain($data->term_data_name);
  }
  // return for JS
  print drupal_to_js($matches);
  // for drupal 7 comment out drupal_to_js and uncomment below
  //drupal_json_encode($matches);

  // we don't need goto next PHP
  exit();
}

 
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn
No Comments  comments 
© Brainstorms of a Webdev
credit