I am building a form using the Drupal 7's Form API... all has been kosher thus far; but looks like I have hit a wall. Looking for guidance/point in the right direction:
A user logs in using CAS (Central Authentication Service). Clicks on a form to create a new record.
At the top of the form, I have a checkbox (which is checked by default), followed by three fields: ID, Name, Phone, and Email.
I pre-populate these fields using the following code:
<?php
//... other code prior to this function
function user_form_form_start($form, &$form_state) {
global $user;
$result = db_query('select u.name, dn.field_full_name_value, pn.field_phone_value, u.mail from field_data_field_full_name dn join field_data_field_phone pn on (dn.entity_id = pn.entity_id) join users u on (pn.entity_id = u.uid) where u.uid = :uid', array(':uid' => $user->uid))->fetchAll();
$myID = isset($result[0]->name) ? $result[0]->name : "";
$myFullName = isset($result[0]->field_full_name_value) ? $result[0]->field_full_name_value : "";
$myPhoneNumber = isset($result[0]->field_phone_value) ? substr($result[0]->field_phone_value, 2) : "";
$myEmailAddress = isset($result[0]->mail) ? $result[0]->mail : "";
$form['tab_user'] = array(
'#type' => 'fieldset',
'#title' => t('User Details'),
'#collapsible' => TRUE, // Added
'#collapsed' => FALSE, // Added
);
$form['tab_user']['user_sameAsAuthor'] = array(
'#type' => 'checkbox',
'#title' => t('Filling it out for myself'),
'#default_value' => isset($form_state['object']->user_sameAsAuthor) ? $form_state['object']->user_sameAsAuthor : TRUE,
// '#required' => TRUE,
);
$form['tab_user'] ['user_id'] = array(
'#type' => 'textfield',
'#title' => t('My CAS ID'),
'#default_value' => isset($form_state['object']->user_id) ? $form_state['object']->user_id : $myID,
// '#required' => TRUE,
);
$form['tab_user']['user_name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
'#default_value' => isset($form_state['object']->user_name) ? $form_state['object']->user_name : $myFullName,
// '#required' => TRUE,
);
$form['tab_user']['user_phone'] = array(
'#type' => 'textfield',
'#title' => t('Phone Number'),
'#default_value' => isset($form_state['object']->user_phone) ? $form_state['object']->user_phone : $myPhoneNumber,
'#attributes' => array('class' => array('phoneNumberField')),
'#size' => 20,
// '#required' => TRUE,
);
$form['tab_user']['user_email'] = array(
'#type' => 'textfield',
'#title' => t('E-mail'),
'#default_value' => isset($form_state['object']->user_email) ? $form_state['object']->user_email : $myEmailAddress,
// '#required' => TRUE,
);
return $form;
}
//... other code after this function
?>
ALL of the above works beautifully! Here's where I am stuck:
If the user unchecks the check box, I would like the user to input a new ID. Based on whatever ID user inputs, how can I "ajaxically" fetch Name, Phone, and Email doing an LDAP lookup?
Any and all help greatly appreciated!
EDIT:
Apologies! Forgot to mention that in my research, I dug through the Form API (of course) and noticed that textfield (https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x#textfield) accepts ajax property (https://api.drupal.org/api/drupal/developer%21topics%21forms_api_reference.html/7.x#ajax). However, the example code does not fully answer my question.
Related
I have two forms on my Drupal page, one form is populating its fields when value of the first form is changed (when you choose an item from a select box). It seems to work fine, untill I try to submit the form, which won't do much, since in my browser it says this error:
[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
<?php
function my_form($form, &$form_state) {
$form['form_1'] = [
'#type' => 'fieldset',
'#title' => "Select box",
'#collapsible' => FALSE,
'#collapsed' => FALSE,
];
$form['form_1']['id'] = [
'#title' => t('Choose:') ,
'#type' => 'select',
'#options' => [
'1' => 'ONE',
'2' => 'TWO',
'3' => 'THREE'
],
'#required' => '1',
'#ajax' => [
'callback' => 'my_form_state_ajax_callback',
'wrapper' => 'form_edit',
],
];
//--------
$form['form_2'] = [
'#type' => 'fieldset',
'#title' => "This is form",
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#prefix' => '<div id ="form_edit">',
'#suffix' => '</div>',
];
$form['form_2']['name'] = [
'#type' => 'textfield',
'#title' => 'Name',
'#required' => TRUE,
];
$form['form_2']['button'] = [
'#type' => 'submit',
'#value' => "Create",
'#submit' => ['my_form_submit'],
];
return $form;
}
function my_form_state_ajax_callback($form, &$form_state) {
$values = $form_state['values'];
$id = $values['id'];
if($id > 0) {
$form['form_2']['name']['#value'] = "this works!";
} else {
if(isset($form['form_2']['name']['#value'])) unset($form['form_2']['name']['#value']);
}
return $form['form_2'];
}
How to fix this error? It doesn't really matter what is inside the callback function, it can be empty and the error will still occur.. What am I doing wrong?
I am trying to create some settings for a module and am following the guide on Drupal.org. I am also comparing my work to existing modules.
The config menu appears in the correct place with the correct fields but when I hit save no input is saved. (I have run cache clear and registry rebuild.)
Would anyone know what I am doing wrong here? I cannot see how my stuff differs.
On my .admin.inc file I have set the form as such:
function contact_page_settings() {
$form = array();
$config = contact_page_default_settings();
$form['#tree'] = TRUE;
$form['contact_page_settings'] = array(
'#type' => 'fieldset',
'#title' => t('Top Section'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'top-title' => array(
'#type' => 'textfield',
'#title' => t('Top title'),
'#default_value' => !empty($config['top-title']) ? $config['top-title'] : '',
),
'top-left' => array(
'#type' => 'text_format',
'#title' => t('Top left'),
'#default_value' => !empty($config['top-left']) ? $config['top-left'] : '',
),
'top-right' => array(
'#type' => 'text_format',
'#title' => t('Top right'),
'#default_value' => !empty($config['top-right']) ? $config['top-right'] : '',
),
);
return system_settings_form($form);
}
On my .module file I have:
function contact_page_menu() {
$items = array();
$items['admin/settings/contact-page'] = array(
'title' => 'Contact Page content',
'page callback' => 'drupal_get_form',
'access arguments' => array('administer site configuration'),
'page arguments' => array('contact_page_settings'),
'type' => MENU_NORMAL_ITEM,
'file' => '/admin/contact_page.admin.inc',
);
return $items;
}
function contact_page_default_settings() {
$defaults = array(
'top-tile' => 'Top title',
'top-left' => 'Top left',
'top-right' => 'Top right',
);
$config = variable_get('contact_page_settings', array());
return array_merge($defaults, $config);
}
OK, so I found out the values were saving - just they were not appearing in my text areas when I reloaded the config page.
The problem was that I was using text_format fields which save data as an array. I needed to get the value property of that array as my default value.
So, I just added ['value'] to the default_value ternary expression:
'#default_value' => !empty($config['top-right']['value']) ? $config['top-right']['value'] : '',
I have created a multiupload field in my node using Multiupload Filefield Widget. I am using the code below to alter the default node form.
There is an ajax based dependent dropdown field in the form i.e city dependent on country.When I select a single country the form work fine. But when I select multiple values form the country list I get the follwing error:
An illegal choice has been detected. Please contact the site administrator.
I get this particular error when there is the multiupload form element present. When I remove the element from $form its works fine with multiple selected values.
Please help me out to solve this problem.Thanks in advance!
function mymodule_form_alter(&$form, &$form_state, $form_id) {
switch ($form_id) {
case 'mynode_node_form':
$country_list = load_countries();
$selected_country = (isset($form_state['values']['country'])) ? $form_state['values']['country'] : key($country_list);
$form['countries'] = array(
'#type' => 'select',
'#title' => t('Select Your Country'),
'#options' => $country_list,
'#default_value' => $selected_country ,
'#ajax' => array(
'callback' => 'city_dropdown_callback',
'wrapper' => 'city_wrapper',
),
'#multiple' => TRUE,
'#required' => TRUE,
);
$cities_list = load_cities($selected_country);
$selected_cities = (isset($form_state['values']['cities'])) ? $form_state['values']['cities'] : key($cities_list);
$form['cities'] = array(
'#type' => 'select',
'#title' => t('Select Your City'),
'#prefix' => '<div id="city_wrapper">',
'#suffix' => '</div>',
'#options' => $cities_list,
'#default_value' => $selected_cities,
'#multiple' => TRUE,
'#required' => TRUE,
);
}
}
function city_dropdown_callback($form,$form_state){
return $form['cities'];
}
I'm having trouble getting the values from a multistep form to insert into the database. All I'm getting is empty values for each field.
Here's the code:
function multistep_profile_menu() {
$items['multistep_profile'] = array(
'title' => t('Multistep Profile'),
'page callback' => 'drupal_get_form',
'page arguments' => array('multistep_profile'),
'type' => MENU_NORMAL_ITEM,
'access arguments' => array('access content'),
);
return $items;
}
function multistep_profile(&$form_state) {
// $form_state['storage']['step'] keeps track of what page we're on.
if (!isset($form_state['storage']['step'])) {
$form_state['storage']['step'] = 1;
}
//stores form data and carries it between steps
$default_value = '';
if (isset($form_state['storage']['values'][$form_state['storage']['step']])) {
$default_value = $form_state['storage']['values'][$form_state['storage']['step']];
}
switch ($form_state['storage']['step']) {
// Step 1 of Form
case 1:
$form['step_one'] = array(
'#title' => t('Step 1'),
'#type' => 'fieldset',
'#description' => t('Just getting started.'),
);
// Full Name
$form['step_one']['full_name'] = array(
'#title' => t('Full Name'),
'#type' => 'textfield',
'#description' => t('Please enter your name.'),
'#required' => TRUE,
'#default_value' => isset($default_value['full_name']) ? $default_value['full_name'] : '',
);
// College/University/Organization
$form['step_one']['college'] = array(
'#type' => 'textfield',
'#title' => t('College/University/Organization'),
'#default_value' => isset($default_value['college']) ? $default_value['college'] : '',
);
// Academic Disciplines
$form['step_one']['academic'] = array(
'#type' => 'textfield',
'#title' => t('Academic Disciplines'),
'#default_value' => isset($default_value['academic']) ? $default_value['academic'] : '',
);
break;
// Step 2 of Form
case 2:
$form['step_two'] = array(
'#title' => t('Step 2'),
'#type' => 'fieldset',
'#description' => t('Almost done.'),
);
// Job Title
$form['step_two']['job_title'] = array(
'#title' => t('Job Title'),
'#type' => 'textfield',
'#description' => t('Please enter your job title.'),
'#default_value' => isset($default_value['job_title']) ? $default_value['job_title'] : '',
);
// Department
$form['step_two']['department'] = array(
'#type' => 'textfield',
'#title' => t('Department'),
'#default_value' => isset($default_value['department']) ? $default_value['department'] : '',
);
break;
// Step 3 of Form
case 3:
$form['step_three'] = array(
'#title' => t('Step 3'),
'#type' => 'fieldset',
'#description' => t('Almost done, part 3.')
);
// Q1
$form['step_three']['q1'] = array(
'#title' => t('Why do you want to develop a globally networked course?'),
'#type' => 'textarea',
'#description' => t(''),
);
break;
//Confirmation
case 4:
$form['thanks'] = array(
'#value' => '<p>'. t('Your Profile is complete.') .'</p>',
);
break;
}
//programmatically display buttons
if ($form_state['storage']['step'] > 1) {
$form['previous'] = array(
'#type' => 'submit',
'#value' => t('<< Previous'),
);
}
if ($form_state['storage']['step'] != 4) {
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Continue >>'),
);
}
else {
$form['finish'] = array(
'#type' => 'submit',
'#value' => t('Finish'),
);
}
return $form;
}
function multistep_profile_submit($form, &$form_state) {
//Save the values for the current step into the storage array.
$form_state['storage']['values'][$form_state['storage']['step']] = $form_state['values'];
//Check the button that was clicked and change the step.
if ($form_state['clicked_button']['#id'] == 'edit-previous') {
$form_state['storage']['step']--;
}
elseif ($form_state['clicked_button']['#id'] == 'edit-next') {
$form_state['storage']['step']++;
}
elseif ($form_state['clicked_button']['#id'] == 'edit-finish') {
//You should store the values from the form in the database here.
dpm($form_state);
// INSERT into DB
$full_name = $form_state['values']['full_name'];
$college = $form_state['values']['college'];
$academic = $form_state['values']['academic'];
$job_title = $form_state['values']['job_title'];
$department = $form_state['values']['department'];
$q1 = $form_state['values']['q1'];
db_query("INSERT INTO {multistep_profile} (full_name, college, academic, job_title, department, q1, created) VALUES
('%s', '%s', '%s', '%s', '%s', '%s', %d)", $full_name, $college, $academic, $job_title, $department, $q1, time());
drupal_set_message(t('Your profile has been saved.'));
unset($form_state['storage']);
//Go to this page after completing the form.
//$form_state['redirect'] = 'node';
}
}
The only value that makes it into the DB is the 'created' date timestamp.
I ran a DPM to check if the values are being carried over between form steps, and they are, I just can't figure out how to get them to insert into the database. Any help?
Looking at your submit function, you (correctly) store the values collected on the different steps under $form_state['storage']['values'][<step_number>]. This matches with the DPM output you posted, i.e. the values show up under $form_state['storage']['values'][1]..., $form_state['storage']['values'][2]..., etc.
But in your final submit processing, you try to access them under $form_state['values'][...], just as if this was a single step form. As your last step does not post any values, you will not find anything there.
So looks like you'd just need to change your final value collection logic to grab the values from the storage (sub)arrays where you have placed them before :)
E.g.:
$full_name = $form_state['values']['full_name'];
would need to be
$full_name = $form_state['storage']['values'][1]['full_name'];
and so on for the other values.
I've a form in my module (mymodule)...
function mymodule_form()
{
$form['mytext'] = array(
'#title' => 'Password',
'#type' => 'password',
'#size' => 10,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Cool!',
);
$form['cool_submit'] = array(
'#type' => 'submit',
'#value' => 'Cool Submit!',
);
return $form;
}
I've used the hook_entity_view hook to display this form under all drupal entities that are displayed.
function mymodule_entity_view($entity, $type, $view_mode, $langcode) {
$entity->content['myadditionalfield'] = mymodule_form();
}
When showing this form, drupal adds a DIV tag to the mytext (password field) by itself. I want to override this and provide my own DIV tags and theme to this form. How do I do it?
Thanks :-)
I worked further on this question to solve it. And the problem got solved. I changed the above code...
function mymodule_entity_view($entity, $type, $view_mode, $langcode) {
$element = array(
'start' => array(
'#type' => 'button',
'#name' => 'start',
'#button_type' => 'submit',
),
'my_text' => array(
'#type' => 'textfield',
'#size' => 30,
'#maxlength' => 50,
),
'my_submit' => array(
'#type' => 'button',
'#name' => 'Submit Discussion',
'#button_type' => 'submit',
),
);
$entity->content['disc_bar'] = $element;
}
And the problem kept creeping up whenever a textfield or a password field was rendered. I checked the type array in systems elements info function (a elements_info hook) and found that textfield and password fields come with a default value for the #theme-wrapper. I tried to override it by this way...
'my_text' => array(
'#type' => 'textfield',
'#size' => 30,
'#maxlength' => 50,
'#theme-wrapper' => '',
),
and It worked. Its not generating any additional division tags... :-)