Submitted by Eric on Sun, 09/13/2009 - 23:41
For some time now I've wanted to write a blog entry about using AHAH to create dynamically generated form elements. After a recent conversation at work regarding usability, I now had a real world example to create: how to use tiered taxonomy to dynamically generate a form. This code snippet will show you how to create a form that creates child select dropdowns based on the parent taxonomy term the user selects.
First I established a multi-tier taxonomy called "AHAH":
For this example I created a menu callback to display my initial form:
<?php function helper_menu() { $items = array(); $items['ahah-form'] = array( 'title' => 'AHAH Form', 'page callback' => 'drupal_get_form', 'page arguments' => array('_helper_callback_ahah_form'), 'type' => MENU_CALLBACK, 'access callback' => 'user_access', 'access arguments' => array('access content'), ); return $items; }
I then defined the page callback to show the initial form:
<?php function _helper_callback_ahah_form() { // define an array to contain form elements $form = array(); // define the top level vid $vid = 2; // fetch a tree of taxonomy elements $tree = taxonomy_get_tree($vid, 0, -1, 1); // loop though taxonomy and collect elements $options = array(); foreach ($tree as $key => $value) { $options[$value->tid] = $value->name; } // create the first select dropdown input $form['select_1'] = array( '#type' => 'select', '#options' => $options, '#title' => t('Select 1'), '#size' => 5, '#multiple' => false, '#ahah' => array( 'event' => 'change', 'path' => 'ahah-form-callback', 'wrapper' => 'wrapper-1', 'method' => 'replace', ), ); // pass the top level vid in the form $form['ahah_vid'] = array( '#type' => 'hidden', '#value' => $vid, ); // create an empty form element to contain the second taxonomy dropdown $form['wrapper_1'] = array( '#prefix' => '', '#suffix' => '', '#value' => ' ', ); // add a form submit button $form['submit'] = array( '#value' => 'Submit', '#type' => 'submit' ); return $form; }
The above form callback produces the following:
Next, I defined a callback to handle the AHAH page request:
<?php // new menu item: function helper_menu() { // ... $items['ahah-form-callback'] = array( 'title' => 'AHAH Form Callback', 'page callback' => '_helper_callback_ahah_form_callback', 'type' => MENU_CALLBACK, 'access callback' => 'user_access', 'access arguments' => array('access content'), ); // ... return $items; } // and, here's the AHAH callback used to create the new form elements: function _helper_callback_ahah_form_callback() { // define a string variable to contain callback output $output = ""; // pull the top level vid from the $_POST data $vid = $_POST['ahah_vid']; // pull the selected dropdown from the $_PODT data $parentVid = $_POST['select_1']; // loop through the taxonomy tree and fetch child taxonomies $options = array(); $tree = taxonomy_get_tree($vid, $parentVid, -1, 1); foreach ($tree as $key => $value) { $options[$value->tid] = $value->name; } // define the second tier select dropdown element $form['select_2'] = array( '#type' => 'select', '#options' => $options, '#title' => t('Select 2'), '#size' => 5, '#multiple' => false, ); // rebuild form object and output new form elements $output .= ahah_render($form, 'select_2'); // render form output as JSON print drupal_to_js(array('data' => $output, 'status' => true)); // exit to avoid rendering the theme layer exit(); } // Lastly, here's a help function pulled from Nick Lewis's blog to alter the form // see: http://www.nicklewis.org/node/967 // NOTE: based on poll module, see: poll_choice_js() function in poll.module function ahah_render($fields, $name) { $form_state = array('submitted' => FALSE); $form_build_id = $_POST['form_build_id']; // Add the new element to the stored form. Without adding the element to the // form, Drupal is not aware of this new elements existence and will not // process it. We retreive the cached form, add the element, and resave. $form = form_get_cache($form_build_id, $form_state); $form[$name] = $fields; form_set_cache($form_build_id, $form, $form_state); $form += array( '#post' => $_POST, '#programmed' => FALSE, ); // Rebuild the form. $form = form_builder($_POST['form_id'], $form, $form_state); // Render the new output. $new_form = $form[$name]; return drupal_render($new_form); }
The above code allows the user to select an option from the top level tier of taxonomy and the AHAH callback will generate the a select dropdown of the child taxonomies as shown below:
On form submission, you'll see that the options the user selected as stored in $form_state['values']['select_1'] and $form_state['values']['select_2']
No comments:
Post a Comment