Often it is useful to dynamically modify forms by adding or removing form elements with Javascript or Ajax. Drupal 6 makes it easy to do that, using the element attribute #ahah which will react to specified events.
Getting started with AHAH (Asychronous HTML and HTTP, which is really just a fancy name for Ajax) is fairly difficult at first, but once you have a reusable pattern it should be fairly easy.
The following example will add a new option into the select dropdown everytime the user clicks add.
Firstly, you need to define the AHAH attribute on the element upon form declaration.
function example_admin_something_form($form_state) {
$form = array();
// The dropdown which gets refreshed when new items are added.
$form['example_dropdown'] = array(
'#type' => 'select',
'#title' => 'Example Dropdown',
'#options' => array(),
'#prefix' => "<div id='example-select-wrapper'>",
'#suffix' => '</div>',
);
// The magical AHAH button. This does not cause a page reload.
$form['add'] = array(
'#type' => 'button',
'#value' => 'Add',
'#ahah' => array(
'event' => 'click',
'path' => "example/ahah/add_option",
'wrapper' => "example-select-wrapper",
'method' => 'replace',
),
);
// A textfield which allows the user to enter in new select options.
$form['new_option'] = array(
'#type' => 'textfield',
'#title' => t('New Option Name'),
);
// Submit button to actually save the form data.
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Save',
);
return $form;
}
Create a menu path which links to your menu handler.
function hook_menu() {
$path['example/ahah/add_option'] = array(
'page callback' => 'example_ahah_add_option_js',
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
return $path;
}
And now for the handler.
function example_ahah_add_option_js() {
// Retrieve the cached form
$form_state = array('submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
// -----
// You can modify the form here to append new options
$new_option = $_POST['new_option'];
$options = $form['example_dropdown']['#options'];
if (!empty($new_option)) {
// If the key isnt important to you, just use this line.
// $form['example_dropdown']['#options'][] = $new_option;
// I use "Array + Array" here as it maintains the keys if necessary.
// array_merge() does not maintain the keys.
$form['example_dropdown']['#options'] = $options + array($new_option);
}
// End editable code
// -----
// Reset the cached form. Without doing this, Drupal will think this
// is an externally modified form attack and ignore the data.
form_set_cache($form_build_id, $form, $form_state);
$form += array('#post' => $_POST, '#programmed' => FALSE);
$form = form_builder($_POST['form_id'], $form, $form_state);
// -----
// Now we should render only the part of the form we wish to update.
// This will provide the output to place into the wrapper.
drupal_json(array(
'status' => TRUE,
'data' => theme('status_messages') . drupal_render($form['example_dropdown']),
));
}
Now the form should append a new option, only if text is entered into the textfield. For more options for the #ahah attribute (such as events, effects or progress bars), see the documentation.
[ Sources ]
- Drupal Documentation for #ahah
You've probably seen this already, but a good place to start when getting an brief overview. - Getting going with AHAH and Drupal 6
This has nice flowcharts and describes (with images) what the #ahah options are. - Drupal 6 AHAH forms: Making New Fields Work
A bare bones code snippet which works and offers some light explanation. It is a good idea to wrap the reusable code fragments into a new function as he did. Would probably better to rename $form in easy_ahah_form_field() to $field.
My tutorial is based upon this code fragment, which ignores step #5 (the submit handler step) in the link below. - Doing AHAH Correctly in Drupal 6
Detailed description of how the process works. This is not noob friendly and will hurt your brain.