Posted by Craz on August 27, 2010 at 8:33am
4 followers
Jump to:
| Project: | Examples for Developers |
| Version: | 6.x-1.x-dev |
| Component: | AJAX Example |
| Category: | support request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | active |
Issue Summary
Hi,
I used the almost exact same code as the example for dependant dropdown except that i linked the dropdown elements to a mysql database.
Problem is that by default evrything seems ok, first dropdown show all options and second shows dependent options based on my master_selection and when i try to select something else in the master one the dependent dropdown disapear, no error, just that .. Also even if i put my master_selection as a default value for the master one it won't do it .. even if an echo show that the var contain the right info .. hopes you can get it clear ...
here's my code:
<?php
function matches_admin($form_state) {
$form = array();
$query = "SELECT * FROM " . "{teams_entries}";
$query_result = db_query($query);
$query2 = "SELECT * FROM " . "{matches_tournaments}";
$query_result2 = db_query($query2);
$form['Add_form'] = array(
'#type' => 'fieldset',
'#title' => t('Add a new match'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['Add_form']['Opponement'] = array(
'#type' => 'fieldset',
'#title' => t('Opponement details'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$teams_names = array();
while ($matches = db_fetch_object($query_result)) {
$teams_names[$matches->tid] = $matches->name;
}
$master_selection = !empty($form_state['values']['home_team']) ? $form_state['values']['home_team'] : $teams_names[25];
$form['Add_form']['Opponement']['home_team'] = array(
'#type' => 'select',
'#title' => t('Home team'),
'#options' => $teams_names,
'#default_value' => $master_selection,
'#description' => t('Select the playing team in this match.'),
'#ahah' => array(
'path' => 'admin/esport/js',
'wrapper' => 'dependent-dropdown-wrapper',
// 'event' => 'change', // default value: does not need to be set explicitly.
),
);
$form['Add_form']['Opponement']['dependent_dropdown_holder'] = array(
'#tree' => TRUE,
'#prefix' => '<div id="dependent-dropdown-wrapper">',
'#suffix' => '</div>',
);
$form['Add_form']['Opponement']['dependent_dropdown_holder']['dependent_dropdown'] = array(
'#type' => 'select',
'#title' => t('Dependent Dropdown (changes based on master dropdown)'),
// when the form is rebuilt during processing (either AJAX or multistep),
// the $master_selction variable will now have the new value and so the
// options will change.
'#options' => matches_get_map_list($master_selection),
);
$form['Add_form']['Opponement']['matches_home_lineup'] = array(
'#type' => 'textfield',
'#title' => t('Home team lineup'),
'#default_value' => '',
'#size' => 30,
'#maxlength' => 255,
'#description' => t("Enter the home team lineup."),
'#required' => FALSE,
);
$form['Add_form']['Opponement']['matches_opponement'] = array(
'#type' => 'textfield',
'#title' => t('Opposite team'),
'#default_value' => '',
'#size' => 25,
'#maxlength' => 255,
'#description' => t("Enter the opposite team."),
'#required' => TRUE,
);
$form['Add_form']['Opponement']['matches_opponement_lineup'] = array(
'#type' => 'textfield',
'#title' => t('Opposite team lineup'),
'#default_value' => '',
'#size' => 30,
'#maxlength' => 255,
'#description' => t("Enter the opposite team lineup."),
'#required' => FALSE,
);
while ($tournaments = db_fetch_object($query_result2)) {
$tournaments_names[] = $tournaments->name;
}
$form['Add_form']['Opponement']['tournaments'] = array(
'#type' => 'select',
'#title' => t('Tournament'),
'#options' => $tournaments_names,
'#description' => t('Select the tournament.'),
);
$form['Add_form']['Opponement']['description'] = array(
'#type' => 'textarea',
'#title' => t('Match description'),
'#cols' => 60,
'#rows' => 5,
'#description' => t('Write details about the match.'),
);
$form['Add_form']['Map_1'] = array(
'#type' => 'fieldset',
'#title' => t('Map 1'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['Add_form']['Map_1']['matches_map_1_SCORE'] = array(
'#type' => 'textfield',
'#title' => t('Home score'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the home score for the first map."),
'#required' => FALSE,
);
$form['Add_form']['Map_1']['matches_map_1_SCORE_VISITOR'] = array(
'#type' => 'textfield',
'#title' => t('Visitor score'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the visitor score for the first map."),
'#required' => FALSE,
);
$form['Add_form']['Map_1']['matches__map_1_MAP_NAME'] = array(
'#type' => 'textfield',
'#title' => t('Map name'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the map name."),
'#required' => FALSE,
);
$form['Add_form']['Map_2'] = array(
'#type' => 'fieldset',
'#title' => t('Map 2'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['Add_form']['Map_2']['matches_map_2_SCORE'] = array(
'#type' => 'textfield',
'#title' => t('Home score'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the home score for the second map."),
'#required' => FALSE,
);
$form['Add_form']['Map_2']['matches_map_2_SCORE_VISITOR'] = array(
'#type' => 'textfield',
'#title' => t('Visitor score'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the visitor score for the second map."),
'#required' => FALSE,
);
$form['Add_form']['Map_2']['matches__map_2_MAP_NAME'] = array(
'#type' => 'textfield',
'#title' => t('Map name'),
'#default_value' => '',
'#size' => 15,
'#maxlength' => 255,
'#description' => t("Enter the map name."),
'#required' => FALSE,
);
$form['Add_form']['submit'] = array('#type' => 'submit', '#value' => t('Save'));
return $form;
}
function matches_get_map_list($key) {
$sql_team = "SELECT * FROM teams_entries WHERE name = '%s'";
$result_team = db_query($sql_team, $key);
while ($team_id = db_fetch_object($result_team)) {
$gid = $team_id->gid;
}
$sql = "SELECT * FROM matches_maps WHERE gid = '%d'";
$result = db_query($sql, $gid);
while ($maps = db_fetch_object($result)) {
$maps_names[$maps->mid] = $maps->name;
}
return $maps_names;
}
function matches_ahah_render() {
$form = matches_callback_helper();
$changed_elements = $form['dependent_dropdown_holder'];
// Prevent duplicate wrappers.
unset($changed_elements['#prefix'], $changed_elements['#suffix']);
$output = drupal_render($changed_elements);
drupal_json(array(
'status' => TRUE,
'data' => $output,
));
}
function matches_callback_helper() {
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
drupal_process_form($form_id, $form, $form_state);
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
return $form;
}
///////////////////////////////////////
///////////////////////////////////////
/////RENDERING MATCHES ADMIN/////
///////////////////////////////////////
///////////////////////////////////////
function matches_admin_page() {
$test = '';
$head = array(
array('data' => t('ID'), 'field' => 'mid', 'sort' => 'asc', 'width' => '30'),
array('data' => t('Opponement'), 'width' => '30'),
array('data' => t('Home score')),
array('data' => t('Visitor score')),
array('data' => t('Opérations'))
);
$sql = "SELECT * FROM matches_entries" . tablesort_sql($head);
$result = db_query($sql);
while ($matches = db_fetch_object($result)) {
$score_home = $matches->map_1_score_home+$matches->map_2_score_home+$matches->map_3_score_home+$matches->map_4_score_home;
$score_visitor = $matches->map_1_score_visitor+$matches->map_2_score_visitor+$matches->map_3_score_visitor+$matches->map_4_score_visitor;
$rows[] = array(
array('data' => $matches->mid),
array('data' => $matches->team),
array('data' => $score_home),
array('data' => $score_visitor),
array('data' => ''.l('edit','admin/team/matches/edit/'. $matches->mid).' - '.l('delete','admin/team/matches/delete/'. $matches->mid).'')
);
}
$test .= theme_table($head, $rows);
$test .= drupal_get_form('matches_admin');
return $test;
}
function matches_admin_submit($form, &$form_state) {
db_query("INSERT INTO {matches_entries} (mid, team) VALUES ('','%s')", $form_state['values']['matches_opponement']);
drupal_set_message(t('Your form has been saved.') );
}
?>All help appreciated, thanks
Comments
#1
Hi - Please start SIMPLE.
Start by just changing the existing dependent dropdown and implementing _ahah_example_get_first_dropdown_options() and _ahah_example_get_second_dropdown_options() using your database instead of the static initialization technique.
Note that the normal situation would be to have an associative array with key=>value instead of the Strings => Strings type thing that drupal_map_assoc() provides.
When you get those two functions implemented against your database, if they're working, the dependent dropdown should work. Then you can go forward from there actually implementing something for your own purposes.
-Randy
#2
Ok, i did what you said and indeed by trying slowly i made it work .. Now another question comes . How can i change multiple drop^down based on a single one ... i already tried a few things but nothing really worked .. any idea ?
if i try this :
<?php
function matches_ahah_render() {
$form = matches_callback_helper();
$changed_elements = $form['Add_form']['Opponement']['dependent_dropdown_holder'];
$changed_elements2 = $form['Add_form']['Opponement']['dependent_dropdown_holder_map2'];
// Prevent duplicate wrappers.
unset($changed_elements['#prefix'], $changed_elements['#suffix']);
unset($changed_elements2['#prefix'], $changed_elements2['#suffix']);
$output = drupal_render($changed_elements);
$output2 = drupal_render($changed_elements2);
$m_op = $output . $output2;
drupal_json(array(
'status' => TRUE,
'data' => $m_op,
));
}
?>
i get a third not working dependent dropdown from nowhere even if my json response is :
"<div class="form-item" id="edit-dependent-dropdown-holder-dependent-dropdown-wrapper">\n <label for="edit-dependent-dropdown-holder-dependent-dropdown">First map: </label>\n <select name="dependent_dropdown_holder[dependent_dropdown]" class="form-select" id="edit-dependent-dropdown-holder-dependent-dropdown" ><option value="3">mp_supermegablowup</option><option value="4">mp_flowers</option></select>\n</div>\n<div class="form-item" id="edit-dependent-dropdown-holder-map2-dependent-dropdown-map2-wrapper">\n <label for="edit-dependent-dropdown-holder-map2-dependent-dropdown-map2">Second map: </label>\n <select name="dependent_dropdown_holder_map2[dependent_dropdown_map2]" class="form-select" id="edit-dependent-dropdown-holder-map2-dependent-dropdown-map2" ><option value="3">mp_supermegablowup</option><option value="4">mp_flowers</option></select>\n</div>\n"#3
Even tried this:
<?php
function matches_ahah_render() {
$form = matches_callback_helper();
_matches_ahah_render_one($form);
_matches_ahah_render_two($form);
}
function _matches_ahah_render_one($form) {
$changed_elements = $form['Add_form']['Opponement']['dependent_dropdown_holder'];
unset($changed_elements['#prefix'], $changed_elements['#suffix']);
$output = drupal_render($changed_elements);
drupal_json(array(
'status' => TRUE,
'data' => $output,
));
}
function _matches_ahah_render_two($form) {
$changed_elements = $form['Add_form']['Opponement']['dependent_dropdown_holder_map2'];
unset($changed_elements['#prefix'], $changed_elements['#suffix']);
$output = drupal_render($changed_elements);
drupal_json(array(
'status' => TRUE,
'data' => $output,
));
}
?>
with no success ...
#4
Sorry, I need you to explain more explicitly what you want to do.
#5
i need same multiple dropdown based on single product
i used ahah but not working
#6
I know this is for drupal6 (im orking with drupal7) but the case is I need to implement dependent dropdowns with retrieved data from a db, but i need these dependent dropdowns to be in the user registration form... any idea how to insert them in the registration form and feed the table 'users´with the choices of the user in these dropdowns?
thanks a lot (and sorry I couldn´t help you)
#7
You use hook_form_alter() to do AJAX in a form that you didn't create. An example would be appreciated here. The most common request is an example of a hook_form_alter of the node page.
The basic dependent dropdown example should be adequate.
#8
I made it, I used #after_build and the dropdowns are in the form now. Still they don't validate and submit with the rest of the form. I guess is not the correct atribute.
Also (and more important, I dont know how to accomplish the "dependent query" Do you know where can i look for an example also?
Here is the code:
<?php
function myform_form_alter(&$form, &$form_state, $form_id) {
//first, let's check if the form is thregistration form or the profile form
if (!($form_id == 'user_register_form' || $form_id == 'user_profile_form')) {
return;
}
//then, let's add a new validate function to the user form to handle the status
$form['#validate'][] = 'company_status_validate';
//now, let's alter the submit function by creating a custom submit (incl. my queries)
$form['#submit'][] = 'company_status_submit';
//also add a dependent dropdown based in a new function made in ajax
$form['#after_build'][] = 'myform_dependent_dropdown';
//add a fieldset for the confirmation of the user's status
$form['account']['member_status'] = array(
'#type' => 'fieldset',
'#title' => t('Confirm you are a company'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
//add a pair of radios buttons for the user to say if he/she is a company
$form['account']['member_status']['im_company'] = array (
'#type' => 'radios',
'#description' => t('You can only enter in %site-name if you are a company, so tell us the truth', array('%site-name' => variable_get('site name', 'drupal'))),
'#default_value' => 0,
'#options' => array(t('I am a company'), t('Well, I am not'))
);
//add a select field with the sector options, withdrawn from db
$form['account']['member_status']['sector'] = array(
'#type' => 'select',
'#title' => t('Sector'),
'#description' => t('Choose the sector of your company'),
'#options' => array(),
);
if (isset($form['account']['member_status']['sector'])) {
$sectors = array();
$result = db_query("SELECT sector_id, sector_name FROM {sectors}");
foreach ($result as $record) {
$sectors[$record->sector_name] = $record->sector_name;
}
$form['account']['member_status']['sector']['#options'] = $sectors;
}
}
/**
* Now let's make the form validation as called in the alter function
*/
function company_status_validate($form, &$form_state) {
global $user;
// did user say you were a company?
if ($form_state['input']['im_company'] <> 0) {
form_set_error('im_company', t('You must be a company, didnt you know that?'));
}
}
/**
* Implements a hook_submit() function
* like this we intercept the original submit in the altered form
*/
function company_status_submit($form, &$form_state) {
global $user;
$sector = $form_state['input']['sector'];
drupal_set_message(t('We have a lot of opportunities for the %sector sector', array('%sector' => $sector)));
$imaco = $form_state['input']['im_company'];
//insert into the db
db_merge('imacompany')
->key(array('uid'=>$user->uid))
->fields(array(
'imaco' => $imaco,
'sector_name' => $sector,
))
->execute();
}
/**
* Implements hook_user_view_alter().
* we are trying to show our results from the db in a new section of the profile "view"
*/
function myform_user_view_alter(&$build) {
global $user;
if ($build['#account']->uid = $user->uid) {
$build['summary']['sector'] = array(
'#type' => 'user_profile_item',
'#title' => t('My sector'),
'#weight' => 5,
);
}
}
/**
* A form with a dropdown whose options are dependent on a
* choice made in a previous dropdown.
*
* On changing the first dropdown, the options in the second
* are updated.
*/
function myform_dependent_dropdown($form, &$form_state) {
//get the list of options to populate the first dropdown
$options_first = _myform_get_sector_options();
// If we have a value for the first dropdown from $form_state['values'] we use
// this both as the default value for the first dropdown and also as a
// parameter to pass to the function that retrieves the options for the
// second dropdown.
$selected = isset($form_state['values']['sector']) ? $form_state['values']['sector'] : key($options_first);
$form['sector'] = array(
'#type' => 'select',
'#title' => 'Economic sector',
'#options' => $options_first,
'#default_value' => $selected,
// Bind an ajax callback to the change event (which is the default for the
// select form type) of the first dropdown. It will replace the second
// dropdown when rebuilt
'#ajax' => array(
// When 'event' occurs, Drupal will perform an ajax request in the
// background. Usually the default value is sufficient (eg. change for
// select elements), but valid values include any jQuery event,
// most notably 'mousedown', 'blur', and 'submit'.
// 'event' => 'change',
'callback' => 'myform_activity_callback',
'wrapper' => 'activity-replace',
),
);
$form['activity'] = array(
'#type' => 'select',
'#title' => t('Economic activities from your chosen sector:'),
// The entire enclosing div created here gets replaced when dropdown_first
// is changed.
'#prefix' => '<div id="activity-replace">',
'#suffix' => '</div>',
// when the form is rebuilt during ajax processing, the $selected variable
// will now have the new value and so the options will change
'#options' => _myform_get_activity_options($selected),
'#default_value' => isset($form_state['values']['activity']) ? $form_state['values']['activity'] : '',
);
return $form;
}
/**
* Selects just the second dropdown to be returned for re-rendering
*
* Since the controlling logic for populating the form is in the form builder
* function, all we do here is select the element and return it to be updated.
*
* @return renderable array (the second dropdown)
*/
function myform_activity_callback($form, &$form_state) {
return $form['activity'];
}
/**
* Helper function to populate the first dropdown. This was accomplished with drupal_map_assoc, but
* i'll try with a db query...
*
* @return array of options
*/
function _myform_get_sector_options() {
$sectors = array();
$result = db_query("SELECT sector_id, sector_name FROM {sectors}");
foreach ($result as $record) {
$sectors[$record->sector_id] = $record->sector_name;
}
return $sectors;
}
/**
* Helper function to populate the second dropdown. This was accomplished with drupal_map_assoc, but
* i'll try with a db query...
*
* @param $key
* This will determine which set of options is returned.
*
* @return array of options
*/
// function _myform_get_activity_options($key) {
// $options = array();
// $chosen_sector = db_query("SELECT sector_name, sector_id FROM {sectors} WHERE sector_id = :sector_id",
// array(':sector_id' => $key,
// ));
// foreach ($chosen_sector as $record) {
// $options[$record->sector_id] = $record->sector_id;
// }
// $matching_activity = db_query("SELECT sector_id, activity_id, activity-name FROM {activities} WHERE sector_id = :sector_id",
// array(':sector_id' => '',
// ));
// foreach ($matching_activity as $record2) {
// $options[$record2->sector_id] = $record2->sector_id;
// }
// return $options;
// }
function _myform_get_activity_options($key = '') {
// RIGHT NOW THERE IS A FAKE SNIPPET, I DONT KNOW HOW TO CONNECT BOTHE DROPDOWNS
$options = array(
$form['input']['sector'] => array(t('yes')),
);
if(isset($options[$key])) {
return $options[$key];
}
}
?>
thanks a lot.
#9
Please use http://drupal.stackexchange.com for support like this. Thanks!