Tripal v1.x AHAH API for modules

ficklin's picture


Tripal Version: 

Dynamic forms in Drupal sometimes need a bit of help.  Such is the case when you use the AHAH functionality of a form element to retrieve new form elements which also have AHAH functionality.  Without any help, the new form elemetns returned through the AHAH ajax call are not AHAH enabled and JQuery events are not bound to the new elements.  As of Tripal v1.0 new API functions are available to help developers.

The following provides an example from the Tripal CV (controlled vocabulary) module where the Tripal AHAH API is used to allow for dynamic form elements.   The examples shown below are for the form that lets a user add new CV terms to an existing vocabulary and supports auto completion.


Step #1.  

In the function for your form you must first initialize the Tripal AHAH functionality.  Below is an example from the tripal_cv_cvterm_form:

function tripal_cv_cvterm_form(&$form_state, $action = 'add') {

  $form = array();


Step #2.

Add to your form an ahah enabled element.  Below is an example from the form that allows site administrators to first choose the vocabulary.  After selection of the vocabulary, an ajax call is made through via AHAH and the entire form is replaced with additional form elements for adding a new cvterm.


  $form['cv_id'] = array(
    '#title' => t('Controlled Vocabulary (Ontology) Name'),
    '#type' => 'select',
    '#options' => $cvs,
    '#required' => TRUE,
    '#default_value' => $cv_id,
    '#ahah' => array(
       'path'    => 'admin/tripal/tripal_cv/cvterm/ahah',
       'wrapper' => 'cvterm-form',
       'event'   => 'change',
       'method'  => 'replace',

Step #3.  

As described in the Drupal forms documentation, you must have a menu item for your AHAH/AJAX which privdes the callback function that should be used for retrieving results. Below is the example menu item that correponds to the AHAH element created in Step #2 above.


  $items['admin/tripal/tripal_cv/cvterm/ahah'] = array(
    'page callback' => 'tripal_cv_cvterm_callback',
    'access arguments' => array('administer site configuration'),
    'type' => MENU_CALLBACK,
Step #4.  
For the following instructions please refer to the example code below.  In the callback function you must first prepare the form using the 'tripal_core_ahah_prepare_form()' function. It takes no arguments and returns the form object.  Next, you can dissect the form object if you like, to only include the form elements you want to render.  In the case of this example we will render the entire form using the 'drupal_render' function.  After rendering the form, you must then generate a settings array that will be used by the Tripal AHAH helper to bind events to the new objects of the form.  Simply call 'tripal_core_ahah_bind_events()' which will return the desired array.  Finally, return a JSON formatted array as shown in the example below:
function tripal_cv_cvterm_callback() {
  $status = TRUE;

  // prepare and render the form
  $form = tripal_core_ahah_prepare_form();   
  $data = drupal_render($form);  

  // bind javascript events to the new objects that will be returned 
  // so that AHAH enabled elements will work.
  $settings = tripal_core_ahah_bind_events();

  // return the updated JSON
      'status'   => $status, 
      'data'     => $data,
      'settings' => $settings,


Replacing an Entire Form

If you are returning a fully re-rendered form as in our example above, you must reset the form action.  It will be rewritten to be the path of the AHAH URL used to re-render the form.  We need to restore the original form action.  We can use the hook_form_alter() Drupal function to do this.  The function from the Tripal CV module is shown below:


function tripal_cv_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == "tripal_cv_cvterm_form") {    
    // updating the form through the ahah callback sets the action of
    // the form to the ahah callback URL. We need to set it back
    // to the normal form URL
    if ($form_state['values']['form_action'] == 'edit') {
      $form['#action'] = url("admin/tripal/tripal_cv/cvterm/edit");
    else {
      $form['#action'] = url("admin/tripal/tripal_cv/cvterm/add");