Drupal Webform Validation (webform_form_alter) - validation

I'm doing some webform validation using webform_form_alter. I'm using webform_form_alter because I switch certain content on a "select" field.
In my webform-form-317.tpl.php I defined new fieldsets I set my fields into this new fieldset and unset the original from the webform.
$form['submitted']['ContactInfo'] = array(
'#type' => 'fieldset',
'#prefix' => '<div id="ContactInfo">',
'#suffix' => '</div>',
'#weight' => -10,
'#title' => 'Contact Information'
);
$form['submitted']['ContactInfo']['phone_home'] = $form['submitted']['phone_home'];
unset($form['submitted']['phone_home']);
in my webform_form_alter I have the following code:
switch ($form_id)
{
case 'webform_client_form_317':
{
$form['#validate'][] = 'validate_form';
}
}
My Validate_form function looks like:
function validate_form($form_id, $form_values)
{
if ($form_values['submitted_tree']['ContactInfo']['phone_home'] == "")
{
form_set_error('phone_error', t('Please enter a home phone number.'));
}
}
The issue is that the $form_values['submitted_tree']['ContactInfo']['phone_home'] comes back as nothing even is the user has inputted something into the textfield.
Any suggestions on what i'm doing wrong?
As a second question in case somebody also the answers, how do I modify the of these textfields to set the class for "form-text required error" so they show up in red with the rest of the mandatory fields.
Thanks

I hope you don't write this code in the webform module, but have made your a custom module for it.
In the first case, your function should be
function validate_form($form, &$form_state) {
if ($form_state['values']['submitted_tree']['ContactInfo']['phone_home'] == "") {
form_set_error('phone_home', t('Please enter a home phone number.'));
}
}
If you are talking about the error class, Drupal add it to all fields that has an error set like is done on the above code. You need to pass in the name of the form field as first param to the form_set_error function.

Related

Laravel Backpack's CRUD data is not showing on custom operation form

I've been tinkering with Backpack for some moment and tried to create a custom operation called "Next Process". Basically, this operation is just an "edit" function with different fields to fill in (because we want the fields on the "create" function to be edited as well, and the filling of the "Next Process" will be done later after creating the data. So we don't want to just utilize the provided CRUD Edit trait).
The problem is, I am unable to show the value of the fields on this custom function's form. If we try to fill the form from scratch (with no existing data), The page works just fine. The value was stored and can be viewed on the "show" page. However, when we tried to go to the "Next Process" page again (now the field has been populated with some data), the existing data is not shown. Updating the form now resets all the existing data to empty, except for the field that we fill just now.
I have included the $this->data['crud'] = $his->crud and $this->data['entry'] = $this->crud->getEntry($id) at the beginning of the function, and passed the $data to the view. The view itself is just a published version of "edit" blade from Backpack's own template.
I have also tried to use the $this->view->getEditCrud() (just in case if the published template is the culprit), but the result is still the same.
What is wrong with this? I attach my code for reference.
public function getProcess($id)
{
$this->crud->hasAccessOrFail('update');
$this->crud->setOperation('process');
$this->crud->setHeading('Process '.$this->crud->entity_name, 'getProcess'); // set the Heading for the create action
$this->crud->setSubheading('Process '.$this->crud->entity_name, 'getProcess'); // set the Subheading for the create action
$this->data['breadcrumbs'] = [
trans('backpack::crud.admin') => backpack_url('dashboard'),
$this->crud->entity_name_plural => url($this->crud->route),
'Process '.$this->crud->entity_name => false
];
// get the info for that entry
$this->data['entry'] = $this->crud->getEntry($id);
$this->data['crud'] = $this->crud;
$this->data['title'] = 'Process '.$this->crud->entity_name;
$this->data['id'] = $id;
$this->crud->getEntry($id);
$this->crud->addField([
'name' => 'support_type',
'label' => 'Support type',
]);
// Redacted: Whole bunch of addField with the 'name' matching the database column's name
// (pretty sure it's not the problem since saving the form updates the specific field
// in the database).
$this->crud->addField([
'name' => 'third_pty_partnership',
'label' => 'Third Party Partnerships',
]);
$this->data['saveAction'] = [
"active" => [
"value" => "save_and_back",
"label" => "Save and go back"
],
"options" => [
]
];
return view('vendor.backpack.crud.processForm', $this->data);
}
Thanks in advance for your help!
Put the addFields before the calls to the info for the entry.

Content type is not saved when altering the node add form

Here, I have alter the add content type form as follows:
function hc_listings_form_alter(&$form, &$form_state, $form_id)
{
// print_r($form_id);
if($form_id =='home_care_popular_search_region_node_form'){
dpm($form,'form');
$selected_states=hc_listings_load_agecare_regions();
// dpm($selected_states,'selected');
reset($selected_states);
$first_state = key($selected_states);
// dpm($first_state,'$first_state');
$form['field_popular_state']=array(
'#type' => 'select',
'#default_value' => array_shift($selected_states),
'#title' => t('Popular State'),
'#description' => t('Home Care Popular State'),
'#options'=>hc_listings_load_agecare_regions(),
'#ajax'=>array(
'callback'=> 'hc_popular_region_form_ajax',
'wrapper'=> 'regions_list',
'event'=>'change',
'method'=>'replace',
),
'#required' => TRUE,
);
$form['field_popular_region']=array(
'#type' => 'container',
'#tree'=>TRUE,
'#prefix'=>'<div id="regions_list">',
'#suffix'=>'</div>'
);
$form['field_popular_region']['list']=array(
'#type' => 'checkboxes',
'#title' => t('Popular Search Regions'),
'#description' => t('Home Care Popular Search Regions'),
'#options'=>get_popular_regions($first_state),
'#required' => TRUE,
);
}
}
And the ajax Callback function is as follows:
function hc_popular_region_form_ajax($form, &$form_state){
if(isset($form_state['values']['field_popular_state'])){
$state=$form_state['values']['field_popular_state'];
hc_my_log($state);
$form['field_popular_region']['list']=array(
'#type'=>'checkboxes',
'#title'=>'Popular Search Regions',
'#description'=>'Home Care Popular Search Regions',
'#options'=>get_popular_regions($state)
);
hc_my_log($form['field_popular_region']['list']);
$form['field_popular_region']['list']=form_process_checkboxes($form['field_popular_region']['list']);
}
// $form_state['rebuild'] = true;
return $form['field_popular_region'];
}
This works but when the ajax callback is called it will execute the dpm($form,'form') (line:5) too. What is the reason for this?
And after that when I am submitting the form by clicking the default Save button in the node add form both popular regions and popular states values are not saved. What will be the cause of that? Should I have to alter the submission of the node too ?
Here ,I have altered the form fields in a wrong way so in the form submission it alerts me with errors saying that the form structure has been changed in my altering.
The error is that it is not directly targetting the specific form field..so it should be corrected as follows:
if($form_id =='home_care_popular_search_regions_node_form'){
$selected_states=hc_get_states();
reset($selected_states);
$first_state = key($selected_states);
dpm($first_state,'$first_state');
$state= (isset($form_state['values']['field_popular_state']['und'][0]['tid']))?$form_state['values']['field_popular_state']['und'][0]['tid']:$first_state;
//popular states field altering
$form['field_popular_state']['und']['#default_value']=$selected_states[$first_state];
$form['field_popular_state']['und']['#options']=$selected_states;
$form['field_popular_state']['und']['#ajax']['callback']='hc_popular_region_form_ajax';
$form['field_popular_state']['und']['#ajax']['wrapper']='regions_list';
$form['field_popular_state']['und']['#ajax']['method']='replace';
$form['field_popular_state']['und']['#ajax']['event']='change';
//popular regions field altering
$form['field_popular_region']['und']['#prefix']='<div id="regions_list">';
$form['field_popular_region']['und']['#suffix']='</div>';
$form['field_popular_region']['und']['#options']=hc_get_popular_regions($state);
}
Ajax callback is as follows:
function hc_popular_region_form_ajax($form, &$form_state){
return $form['field_popular_region'];
}
Note: the method hc_listings_load_agecare_regions() has been changed to hc_get_states()

Drupal ajax form, partial render

Good day.
I created custom form in my module and defined submit button like this:
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#ajax' => array(
'callback' => 'fmg_addbanner_ajax_callback',
'method' => 'replace',
'wrapper' => 'banner_add_wrapper'
)
);
Then outputted my form like this:
$form = drupal_get_form('fmg_banner_add_form', $region_id);
print render($form);
But ajax requests don't work. I think because of there are no needed drupal js files. How can I solve this problem? Thanks.
The normal case will be to have #ajax attached to a common input, like checkbox, text box etc.
The behavior is that when user change the input value, it'll fire your callback through ajax and send entire form over, and then you can process this form behind the scene and adjust certain things before sending the form back and change the element to the wrapper you defined.
One of the question that I had for partial form rendering is when I need to do some ajax call or inject partial form element to certain area of the page while keeping the integrity of the form rendering. (I don't know exactly what form build did, i guess i don't want to know)
Since form rendering uses the renderable array, if you just want to extract certain element, you could just do
$form = drupal_get_form('application_form');
$body = render($form['body']);
The following is a real example that i took a form and split into header, footer and the rest of form elements.
// get a form for updating application info.
$form = drupal_get_form('pgh_awards_review_application_form', $app);
$elements = array();
$form_render = render($form);
$elements = array(
'qualify' => render($form['qualify']),
'threshold_met' => render($form['threshold_met']),
'submit' => render($form['submit']),
);
if (preg_match('/<form.+div>/', $form_render, $matches)) {
$elements['header'] = $matches[0];
}
if (preg_match('/<input type="hidden".+form>/s', $form_render, $matches)) {
$elements['footer'] = $matches[0];
}
$vars['form'] = $elements;
It's definitely not pretty approach, it just serves the needs at the moment.

Drupal Form API : display the same form again with AJAX, but with different values, on submit

this is my first post on Stackoverflow, after reading perhaps hundreds of thoughtful questions and no less useful answers.
My point is, today, I never found an (even dirty) way to do what I intend to do, and never managed to find an answer, although it seems quite improbable that no one ever had the same request and/or problem.
Which is, by the way...
Calling the same form again with AJAX, but with different values than those previously entered by the user
The idea
I've got a Drupal Form (a normal form built with Drupal Form API) with textfields and an AJAX-ified submit button. This form is displayed through an AJAX call and is itself AJAX-ified, so.
When I click on 'Submit', I want to do some stuff like looking in the database, updating some values, etc, based on what the user entered in the form. And then, I want to ajax-display the same form again, but with different values than those entered by the user in the first instance of the form.
Everything goes fine with doing whatever I want during the processing, but whatever I do, no matter what, I face the same problem again and again :
The problem
When the new instance of the form is displayed, it is displayed with the previous values (those entered by the user). I never was able to display other values than those previously here in the form when "Submit" was clicked in the previous instance of the form.
Simple example
What I'm actually trying to do is quite complex, with several ajax_commands and a bit of processing, but here is a simpler example that faces exactly the same problem :
function ajax_first_callback_to_my_form($type = 'ajax') {
// here the first instance of the form is ajax-called. No problem with that.
$mail = 'example#mail.com';
$first_message = 'Please enter an email address...';
$commands = array();
$commands[] = ajax_command_replace('#my_ajax_wrapper', display_my_form($mail, $first_message));
$page = array('#type' => 'ajax', '#commands' => $commands);
return($page);
}
function display_my_form($mail, $message) {
// the function used to display the form.
// it can be called by the first ajax callback (the previous function in this example)
// or by the ajax callback triggered by clicking 'submit' on the form itself.
$form = drupal_get_form('my_form', $mail, $message);
$display = '<div id="my_ajax_wrapper">';
$display .= render($form);
$display .= '</div>';
return $display;
}
function my_form($form, &$form_state, $mail, $message) {
// the form constructor
$form = array (
'email' => array (
'#type' => 'textfield',
'#default_value' => $mail,
'#suffix' => '<div id="my_message">'.$message.'</div>',
),
'submit' => array (
'#type' => 'submit',
'#ajax' => array (
'callback' => 'my_ajax_callback', ),
),
);
}
function my_ajax_callback($form, &$form_state) {
// triggered by clicking 'submit' in the form
$mail = $form_state['values']['email'];
if ($mail == 'correct_mail#gmail.com') {
$new_mail = 'different_mail#gmail.com';
$new_message = 'You entered a correct email and here is your new one';
} else {
$new_mail = $mail;
$new_message = 'You entered an incorrect mail, please correct it';
}
$commands = array();
$commands[] = ajax_command_replace('#my_ajax_wrapper', display_my_form($new_mail, $new_message));
$page = array('#type' => 'ajax', '#commands' => $commands);
return($page);
}
function my_form_submit($form, &form_state) {
// my_form submit handler
$form_state['rebuild'] = true; // appears necessary, otherwise won't work at all
}
Okay, it was quite a long piece of code but it seemed useful to fully understand my question.
Processing stuff happens correctly...
All the stuff I want to do in my_form_submit or in my_ajax_callback is properly done. If I check the variables in display_my_form() they are correctly updated.
... but the new instance of the form doesn't take it into account
But whatever I can try, the next time the form is displayed with AJAX, the email field will be 'example#mail.com' as its default value (or any different mail entered by the user), and the message div will be filled with 'Please enter an email address...'.
I tried MANY ways of doing this differently, putting the after-submit processing in the ajax callback, in the my_form_submit function, using $_SESSION variables instead of passing them through the different functions, using the database... None of this works.
What to do ?
Quite annoying. This is not the first time I encountered this problem. Last time I could find a workaround, simply by giving up this idea of re-displaying the same form through AJAX, but now I really would appreciate being able to do this.
Could the problem be related to $form_state['rebuild'] ?
By the way, I'm curious about it : have you encountered this problem before ? Is it something simple which I'm missing out ? If it's a bug, could this bug be Drupal-related, or AJAX-related... ?
Any help or ideas will be truly appreciated. Thank you for your time.
I came up with a solution to this one :
If you are to display the same form again with AJAX, for instance with this function (called by your AJAX callback), no matter what you'll do, it will display the same values again and again :
// It doesn't work :
function display_my_form($mail, $message) {
$form = drupal_get_form('my_form', $mail, $message);
$display = '<div id="my_ajax_wrapper">';
$display .= render($form);
$display .= '</div>';
return $display;
}
If you want to change the fields values when refreshing the form, you have to update the form manually, after having called it again, by adding this kind of line :
// It works :
function display_my_form($mail, $message) {
$form = drupal_get_form('my_form', $mail, $message); // $variables are simply ignored if the form is already displayed. Rebuilding it won't change a thing.
$form['email']['#default_value'] = $mail; // update a part of the form
$form['email']['#suffix'] = $message; // update another part of the form
$display = '<div id="my_ajax_wrapper">';
$display .= render($form);
$display .= '</div>';
return $display; // sends $display to our AJAX callback, and everything's fine now
}
Contrary to easy belief one (such as... me) can first have about it, the form doesn't take into account the variables it's being sent with drupal_get_form, when already constructed and recalled by AJAX.
It's just not enough to update the variables, and do drupal_get_form again. You have to do drupal_get_form, and afterwards manually update the parts of the form you want updated.
Hope this will help someone.
Well I am quite confident about your issue if this is the case:
$commands[] = ajax_command_replace('#my_ajax_wrapper', display_my_form($new_mail, $new_message));
The problem is not anything else its just the id you are passing.You need a class and not the id "#my_ajax_wrapper", because id might get changed but class won't in this case.
Try with this you should get the result as you want.
Note: to make it work, one needs to add this in form_submit handler:
function my_form_submit($form, &$form_state)
{
$form_state['rebuild'] = true;
}

Help with ajax callback and drupal_process_form

I have a form that is added through the nodeapi displayed only on view mode. Users can select an item from a select menu and their choice will automatically get saved to the database with a hook_menu callback on change. If the user has javascript disabled, it'll submit normally with the form api. This is all working fine, but now for security reasons I want to submit the ajax version via the form api too. My form_name_submit is simple like:
function mymodule_test_form_submit($form, &$form_state) {
global $user;
db_query("INSERT INTO {mymodule} (nid, uid, status, created) VALUES (%d, %d, %d, " . time() . ")", $form['#parameters'][2], $user->uid, $form_state['values']['mymodule_status']);
}
My ajax:
$('.mysubmit').css('display', 'none');
$('.myclass').change(function() {
$.ajax({
type: 'POST',
url: Drupal.settings.basePath + 'mymodule/set/' + $nid + '/' + $('.myclass').val(),
dataType: 'json',
data: { 'ajax' : true, 'form_build_id' : $('#mymodule-form input[name=form_build_id]').val() }
});
});
And my callback function:
function mymodule_set($nid, $status) {
$form_build_id = $_POST['form_build_id'];
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
$form['#post'] = $_POST;
$form['#redirect'] = FALSE;
$form['#programmed'] = FALSE;
$form_state['post'] = $_POST;
drupal_process_form($form_id, $form, $form_state);
}
Originally my callback function was about the same as my submit function, but now I'm trying to use the submit function with ajax as well. Is this the right way to use drupal_process_form? The form is grabbed from the cache, it get's validated and submitted if no errors? I'm using some code from this tutorial to apply to my situation: http://drupal.org/node/331941 There doesn't seem to be any examples of what I'm trying to do. I also have $form['#cache'] = TRUE; in my form function.
How does drupal_process_form compare the submitted values with the original form to check for integrity? Am I supposed to add my values to the form_state since the form state will be empty with ajax. Been stuck on this for a few days, hopefully someone has experience with this.
Thanks.
I had to do somenthing similar to you in the past and read the same tutorial you posted, unfortunately there isn't much information avalaible about this and it was headache for me to make it work. I don't remember well the details but I was taking a look to the code I wrote and here are a couple of suggestions that may work for you:
Do not submit the form using your own jQuery code, instead use the new "#ahah" property of form elements that can be used for calling your callback in the onchange of the select http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/6#ahah
IF you are doing this in a node form, adding the #ahah property in a form alter may not work, I remember having seen an issue about this that wasn't solved at that moment. if this is the case, use this code for attaching the ahah binding, you'll not need "efect", "method" or "progress" since you just want to submit the form, not to change anything about it:
function YOURMODULE_form_alter(&$form, $form_state, $form_id) {
if ('YOURCONTENTTYPE_node_form' == $form_id) {
//the only way I could make it work for exisiting fields is adding the binding "manually"
$ahah_binding = array(
'url' => url('YOURCALLBACKPATH'),
'event' => 'change',
'wrapper' => 'FIELD-wrapper',
'selector' => '#FIELD',
'effect' => 'fade',
'method' => 'replace',
'progress' => array('type' => 'throbber'),
);
drupal_add_js('misc/jquery.form.js');
drupal_add_js('misc/ahah.js');
drupal_add_js(array('ahah' => array('FIELDd' => $ahah_binding)), 'setting');
//force the form to be cached
$form['#cache'] = TRUE;
}
}
Here is my callback function, note that it has some modifications from the tutorial you posted:
function YOURMODULE_js() {
// The form is generated in an include file which we need to include manually.
include_once 'modules/node/node.pages.inc';
// We're starting in step #3, preparing for #4.
//I have to add the 'rebuild' element, if not an empty node was created
$form_state = array('storage' => NULL, 'submitted' => FALSE, 'rebuild' => TRUE);
$form_build_id = $_POST['form_build_id'];
// Step #4.
$form = form_get_cache($form_build_id, $form_state);
// Preparing for #5.
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
// if you want to do any modification to the form values, this is the place
// Step #5.
drupal_process_form($form_id, $form, $form_state);
// Step #6 and #7 and #8.
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Final rendering callback.
drupal_json(array('status' => TRUE, 'data' => $output));
}
As I said before there are details that I have forgot but maybe this will help you.
Good Luck.

Resources