Drupal: full cycle form with parameters and response page - validation

I am trying to make a full cycle form with parameters and response page. Form is working OK, but response page is coming up black. Anyone have a suggestion or model example.
function module99_menu(){
$items = array();
// inital form
$items['module-99'] = array(
'title' => t('Export'), // Page title
'page callback' => 'fn_module99', // function to call when this page is called
'access arguments' => array('access content'), // An array of arguments to pass to the access callback function.
'description' => t('Export'),
'type' => MENU_CALLBACK,
);
// response page
$items['my_module-99-response/%/%'] = array(
'title' => t('Response Page'), // Page title
'page callback' => 'fn_module99_response', // function to call when this page is called
'page arguments' => array(0,1), // pass with arg(0) and arg(1)
'access arguments' => array('access content'),
'description' => t('Export - response form'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
function fn_module99() {
return drupal_get_form('module99_my_form');
}
function module99_my_form_validate($form, &$form_state) {
// do some validation
}
function module99_my_form_submit($form, &$form_state) {
// do some stuff
drupal_set_message(t('The form has been submitted.'));
$parms = "p1=" . "A" . "&p2=" . "B" ;
$form_state['redirect'] = array('my_module-99-response', $parms);
}
function fn_module99_response($parm1,$parm2) {
$output = $parm1 . $parm2;
return $output;
}
function module99_my_form($form_state){
$form = array();
$form['email'] = array(
'#type' => 'textfield',
'#title' => t('E-mail address') ,
'#size' => 64,
'#maxlength' => 64,
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}

You should change the redirect a bit:
$form_state['redirect'] = array("my_module-99-response/$param_a/$param_b");
Also in your hook_menu you want to change the page arguments:
$items['my_module-99-response/%/%'] = array(
'page arguments' => array(1,2),
);
This will match the two % in your url, as 0 is 'my_module-99-response'.

I don't know if it will help, but the standard method is to use drupal_get_form on the hook menu with the form id of the form as a parameter. I'm not sure what you are trying to do with the arguments?
$items['my_module-99-response/'] = array(
'title' => t('Response Page'), // Page title
'page callback' => 'drupal_get_form',
'page arguments' => array('fn_module99_response'),
'access arguments' => array('access content'),
'description' => t('Export - response form'),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
You should also specify a submit handler in the form using the '#submit' property (make sure you pass an array). Do validation in the same way while you are at it.
function module99_my_form($form_state){
$form = array();
$form['email'] = array(
'#type' => 'textfield',
'#title' => t('E-mail address') ,
'#size' => 64,
'#maxlength' => 64,
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
$form['#submit'] = array('module99_my_form_submit') ;
$form['#validate'] = array('module99_my_form_validate') ;
return $form;
}

$form_state['redirect'] = array("my_module-99-response/$param_a/$param_b");
this works great except drupal mangles the slashes with encoding

Related

Form input not cleared after ajax submission

I have a form with one field and a submit button with ajax submission option like following -
public function buildForm(array $form, FormStateInterface $form_state, $id = 0)
{
$form['fieldset']['message'] = array(
'#type' => 'textfield',
'#default_value' => "",
'#required' => true,
'#attributes' => array(
'placeholder' => t('write here'),
),
);
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Send'),
'#attributes' => array(
'class' => array(
),
),
'#ajax' => [
'callback' => [$this, 'Ajaxsubmit'],
'event' => 'click']
);
return $form;
}
The ajax function is following -
public function Ajaxsubmit(array $form, FormStateInterface $form_state)
{
$user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());
$db_values = [
"message" => $form_state->getValue("message"),
"date_create" => date("Y-m-d H:i:s"),
];
$save = DbStorage::Insert($db_values);
//$('#mychat_form input').val("");
//$form_state->setValue('content', NULL);
$response = new AjaxResponse();
if ($form_state->hasAnyErrors() || !$save) {
$response->addCommand(new AlertCommand('something wrong!'));
} else {
$message = DbStorage::Get(["id" => $save]);
$send_id = $message->send_id;
$build = [
'#theme' => "chat_view",
'#message' => $message,
'#sender' => $send_id,
'#current_user' => true
];
$ans_text = render($build);
$response->addCommand(new AppendCommand('#mychat', $ans_text));
}
return $response;
}
Here form data submission is working fine. But input data is not cleared after submission. I tried to clear it from my javascript using -
$('#my_form input').val("");
But the problem is my javascript file is called every 3 seconds and the form input is also cleared in every 3 seconds. this is problematic for users. Is there any other way to clear the form input after the ajax submission ? Can i do anything inside Ajaxsubmit function ?
You can use InvokeCommand for doing it.
For e.g: to clear an input value $('#my_form input').val(""); in ajax response
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\AppendCommand;
:
$form['fieldset']['message'] = array(
'#type' => 'textfield',
'#default_value' => "",
'#required' => true,
'#attributes' => array(
'placeholder' => t('write here'),
'class' => ['custom-class'],
),
);
In Ajax function
:
$build = [
'#theme' => "chat_view",
'#message' => $message,
'#sender' => $send_id,
'#current_user' => true
];
$response->addCommand(new AppendCommand('#mychat', $build));
$response->addCommand(new InvokeCommand('.custom-class', 'val', ['']));

Drupal 7 ajax and session

I have created a .module file which includes a form and an ajax call back. Here is a simple code of the .module file:
function form_registration_form($form, &$form_state) {
$form['registration']['email'] = array(
'#type' => 'textfield',
'#required' => TRUE,
'#size' => 44,
'#maxlength' => '80',
'#attributes'=> array('placeholder' => 'Email','data-email'=>'','data-min-chars'=>'5'),
);
$form['registration']['password'] = array(
'#type' => 'password',
'#required' => TRUE,
'#size' => 44,
'#maxlength' => '80',
'#attributes'=> array('placeholder' => 'Password'),
);
$form['registration']['submit'] = array(
'#value' => 'SIGN IN',
'#type' => 'submit',
'#submit' => array('form_registration_handler'),
);
return $form;
}
and in the function form_registration_handler I create a session (name it test).
Here is the ajax menu call back function:
function mymodule_menu() {
$items['ajax/innerAction'] = array(
'title' => 'Browser Inner Action',
'page callback' => 'innerActionCallBack',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
return $items;
}
function innerActionCallBack() {
header('Access-Control-Allow-Origin: *');
drupal_session_start();
print session_id();
}
This function is used on my page.tpl.php file to create an ajax to server.
The problem here is when I call the ajax, the session id is different when
I refresh the browser and I can not retreive the Session test that I created earlier.
Do you know what is happening here. Any helps are really appreciated.
Ok so I have figured out the answer. I have to login the user into Drupal first so that Drupal can retrieve the correct sessionID.

How to save a custom form image to a custom user field

I have a custom form that creates a new user and fills in a number of custom fields for that user. One of these fields is a custom image (not the system avatar image).
I can get the image uploaded to the server through the form, but can't get it into the appropriate field. Here is my (custom module) code so-far.
function newacc_freebusiness_form($form, &$form_state) {
$form['bussimage'] = array(
'#title' => t('Upload an image that shows off your business.'),
'#type' => 'managed_file',
'#description' => t('Max size of 3Mb and filetype of jpg jpeg or png'),
'#upload_location' => 'public://bussimages/',
'#upload_validators' => array(
'file_validate_extensions' => array('png jpg jpeg'),
'file_validate_size' => array(3*1024*1024),
),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
$form['#validate'][] = 'newacc_freebusiness_validate';
return $form;
}
function newacc_freebusiness_validate($form, &$form_state) {
$bussimage = $form_state['values']['bussimage'];
$file = file_load($bussimage);
$bussimage = image_load($file -> uri);
image_save($bussimage);
$bussimage = image_load($file -> uri);
$edit = array(
'name' => 'name',
'mail' => 'mail#mail.com',
'status' => 0,
'language' => 'en',
'init' => 'mail#mail.com',
'roles' => array(8 => 'Promoter'),
'field_business_image' => array(
'und' => array(
0 => array(
'value' => $bussimage,
),
),
),
);
user_save(NULL, $edit);
}
This is throwing the error message:
Notice: Undefined index: fid in file_field_presave() (line 219 of /var/www/drupal_site/modules/file/file.field.inc).
I have tried so many tricks now and googled so long that I can't even explain what I have and haven't tried anymore!
Any help please.
OK - solved this. The clue was in the error message and the solution was very simple! Here is the code:
function newacc_freebusiness_form($form, &$form_state) {
$form['bussimage'] = array(
'#title' => t('Upload an image that shows off your business.'),
'#type' => 'managed_file',
'#description' => t('Max size of 3Mb and filetype of jpg jpeg or png'),
'#upload_location' => 'public://bussimages/',
'#upload_validators' => array(
'file_validate_extensions' => array('png jpg jpeg'),
'file_validate_size' => array(3*1024*1024),
),
'#required' => TRUE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
$form['#validate'][] = 'newacc_freebusiness_validate';
return $form;
}
function newacc_freebusiness_validate($form, &$form_state) {
$bussimage = $form_state['values']['bussimage'];
$file = file_load($bussimage);
$edit = array(
'name' => 'name',
'mail' => 'mail#mail.com',
'status' => 0,
'language' => 'en',
'init' => 'mail#mail.com',
'roles' => array(8 => 'Promoter'),
'field_business_image' => array(
'und' => array(
0 => array(
'fid' => $file -> fid,
),
),
),
);
user_save(NULL, $edit);
}
All Drupal was looking for was the file fid in the array. Don't know why I initially assumed it had to be more complicated than this.

dynamic dropdown by #ajax DRUPAL 7

I am trying to make dynamic 3 dropdown(DD) by #ajax property of drupal 7..
1st DD contains country list(coming from db)
2nd DD contains states list(coming from db)
3re DD contains city list(coming from db)
problem is as i choose country ..my states DD show states accordingly..by how to trigger my states DD so that my city DD also got updated at the same time my state updated..I have to click on states table only then my cities DD changes..
---MY CODE IN FORM_ALTER IS THIS---
$options_first = iripple_classifieds_country_list();
$selected = isset($form_state['values']['country_by_alter']) ? $form_state['values']['country_by_alter']: key($options_first);
$options_first = iripple_classifieds_country_list();
$form['country_by_alter'] = array(
'#type' => 'select',
'#title' => t('Country'),
'#validated' => TRUE,
'#options' => $options_first,
'#weight' => 5,
//'#disabled' =>TRUE,
'#ajax' => array(
'callback' => 'iripple_classifieds_country_callback',
'wrapper' => 'statereplace',
'effect' => 'fade',
// 'event' => 'onload'
),
'#attributes' => array(
// 'onload' => "jQuery('#edit-country-by-alter').trigger('click')"
)
);
$options_second = iripple_classifieds_state_list();
$selected_state = isset($form_state['values']['state_by_alter']) ? $form_state['values']['state_by_alter']: key($options_second);
$form['state_by_alter'] = array (
'#type' => 'select',
'#title' => t('State'),
'#options' => iripple_classifieds_selected_states($selected),
'#default_value' => isset($form_state['values']['state_by_alter']) ? $form_state['values']['state_by_alter']:'',
'#weight' => 7,
'#validated' => TRUE,
'#prefix' => '<div id="statereplace">',
'#suffix' => '</div>',
'#ajax' => array(
'callback' => 'iripple_classifieds_state_callback',
'wrapper' => 'cityreplace',
'event' => 'change'
)
);
$form['city_by_alter'] = array(
'#type' => 'select',
'#title' => t('City'),
'#options' => iripple_classifieds_selected_cities($selected_state),
'#default_value' => isset($form_state['values']['city_by_alter']) ? $form_state['values']['city_by_alter']:'',
'#weight' => 8,
'#validated' => TRUE,
'#prefix' => '<div id="cityreplace">',
'#suffix' => '</div>',
);
From what I have tried in the past, unless you aren't using the field module, the Hierarchial Select module with either your custom module based off the included hs_smallhierarchy or the hs_taxonomy modules/select menus would work for your three level select element.
The hs_taxonomy module has the database calls you would need, otherwise you can just pass the information and use the former. I've search a lot of different sites and this is something I've tried to accomplish for some time. Looking at their code would show you the Javascript you would have to use and process for the second and third select items because as you stated, unless it isn't stated one page load you will run into problems.
I've gotten a 6 Level Ebay Category to change the options correctly, but it won't update $form_state after a certain level.
function ajax_pra_menu() { $items['ajax_pra'] = array(enter code here
'title' => 'ajax Practice',
'page callback' => 'drupal_get_form',
'page arguments' => array('ajax_pra_dependent_dropdown'),
'access callback' => TRUE,enter code here` );
return $items;
}
function ajax_pra_dependent_dropdown($form, &$form_state) { $options_first = _ajax_pra_get_first_dropdown_options();
$options_two = _ajax_pra_get_second_dropdown_options();
$selected = isset($form_state['values']['dropdown_first']) ? $form_state['values']['dropdown_first'] : key($options_first);
$select_two = isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : key($options_two);
$form['dropdown_first'] = array(
'#title' => 'Item',
'#type' => 'select',
'#options' => $options_first,
'#default_value' => $selected,
'#ajax' => array(
'callback' => 'ajax_pra_dependent_dropdown_callback',
'wrapper' => 'dropdown-second-replace'
),
);
$form['dropdown_second'] = array(
'#title' => $options_first[$selected] . ' ' . t('type'),
'#type' => 'select',
'#prefix' => '<div id="dropdown-second-replace">',
'#suffix' => '</div>',
'#options' => _ajax_pra_get_second_dropdown_options($selected),
'#default_value' => isset($form_state['values']['dropdown_second']) ? $form_state['values']['dropdown_second'] : '',
'#ajax' => array(
'callback' => 'ajax_pra_two_dependent_dropdown_callback',
'wrapper' => 'dropdown-third-replace',
),
);
$form['dropdown_third'] = array(
'#title' => $options_two[$select_two] . ' ' . t('third'),
'#type' => 'select',
'#prefix' => '<div id="dropdown-third-replace">',
'#suffix' => '</div>',
'#options' => _ajax_pra_get_third_dropdown_options($select_two),
'#default_value' => isset($form_state['values']['dropdown_third']) ? $form_state['values']['dropdown_third'] : '',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('save'),
);
}
function ajax_pra_dependent_dropdown_callback($form,$form_state)
{
return $form['dropdown_second'];
}
function ajax_pra_two_dependent_dropdown_callback($form,$form_state)
{
return $form['dropdown_third'];
}
function _ajax_pra_get_first_dropdown_options()
{
return drupal_map_assoc(
array(
t('Car'),
t('Bike'),
t('Mobile'),
)
);
}
function _ajax_pra_get_second_dropdown_options($key = ' ')
{
$options = array(
t('Car') => drupal_map_assoc(
array(
t('bmw'),
t('audi'),
)
),
t('Bike') => drupal_map_assoc(
array(
t('honda'),
t('suzuki'),
)
),
t('Mobile') => drupal_map_assoc(
array(
t('nokia'),
t('micro'),
)
),
);
if (isset($options[$key]))
{
return $options[$key];
}
else{
return array();
}
}
function _ajax_pra_get_third_dropdown_options($key = '')
{
$options = array(
t('bmw') => drupal_map_assoc(
array(
t('bmw x3'),
t('bmw x6'),
)
),
t('honda') => drupal_map_assoc(
array(
t('city'),
t('accord'),
)
),
);
if(isset($options[$key]))
{
return $options[$key];
}
else
{
return array();
}
}

Drupal Form APi Checkbox states

So I have create my checkbox in my form
$form['existing_customer'] = array(
'#type' => 'checkbox',
'#title' => t('Are you an existing customer'),
'#ajax' => array(
'callback' => 'checkbox_selected',
'wrapper' => 'subject',
),);
This calls my function and changes the values in my checkbox
The problem is I cannot get it to switch back if it is unchecked
function checkbox_selected(&$form, &$form_state) {
if ($form_state['values']['existing_customer'] == 1) {
$my_options = array( 'select' => t('Select'), 'mr' => t('Mr'), 'mrs' => t('Mrs'), 'miss' => t('Miss'), 'ms' =>t('Ms'), 'sir' =>t('Sir'), 'dr' => t('Dr'), 'prof' => t('Prof') );
}
elseif ($form_state['values']['existing_customer'] == 0){
$my_options = array( 'seconfZ' => t('jimmy'), 'mr' => t('Mr'), );
}
$form['subject'] = array(
'#type' => 'select',
'#title' => t('Subject'),
'#options' => $my_options//$form['subject_options']['#value']
);
return $form['subject'];
}
I thought I could do a switch on the checkbox value or state but no joy?
Oftentimes, when you use the Form API #ajax system, the wrapper that you specify is actually replaced with another element AFTER drupal_html_id() has been called again on the element wrapper. So I would check the markup of the "subject" element in Firebug/Web Inspector after your AJAX stuff happens--I'm betting that the wrapper div is now something like "subject--1".
To fix this, you need to manually set a wrapper div on the item you are replacing--one that won't change when the form is rebuilt. For example, in your form builder:
$form['existing_customer'] = array(
'#type' => 'checkbox',
'#title' => t('Are you an existing customer'),
'#ajax' => array(
'callback' => 'checkbox_selected',
'wrapper' => 'subject-wrapper',
),
);
$form['subject'] = array(
'#prefix' => '<div id="subject-wrapper">',
...
`#suffix' => '</div>',
);
Hope that helps!

Resources