Hello,
I'm developing a module that uses a form.
The module reads the two textbox value (defined in _form), validates the data (_form_validation) and inserted in the db (_form_submit).
I have done without ajax submit and it works fine.

Now i need to this using AJAX submit.
I tried to follow the examples (eg AJAX example) but I found problems with data validation:
_form_validation hook is called but if the procedure find a validation error it call anyway _form_submit hook... this is wrong!

Can anyone help me to fix?

This is a piece of code

function example_form($_data=NULL)
{
  $form['username'] = array(
    '#type' => 'textfield',
    '#title' => t('User`s username'),
    '#required' => TRUE,
  );
  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => t('E-mail'),
    '#required' => TRUE,
  );
  $form['sub']['insert'] = array(
    '#type' => 'button',
    '#value' => t('Save record'),
	'#ajax' => array(
      'callback' => 'example_form_submit',
      'wrapper' => 'example-form',
    ),
  );
  return $form;
}

function example_form_validate($form, &$form_state)
{
	if (!valid_email_address($form_state['values']['email'])) {
	form_set_error('email', t('That e-mail address is not valid.'));

}
function example_form_submit($form, &$form_state)
{
    <insert data into db>
}

Comments

Fabrice_’s picture

no one can help me?

trampjuice’s picture

Off the top of my head I would say instead of type => button it should be type => submit.

http://api.drupal.org/api/drupal/developer--topics--forms_api_reference....

alexkb’s picture

I don't think it's the submit thats the problem, it's more likely the names you have for your wrapper.

I had major issues trying to get my errors to show up to. But after several hours got something working.. so to take your code:


function example_form($_data=NULL){
  $form['mywrapper']['username'] = array(
    '#type' => 'textfield',
    '#title' => t('User`s username'),
    '#required' => TRUE,
  );
  $form['mywrapper']['email'] = array(
    '#type' => 'textfield',
    '#title' => t('E-mail'),
    '#required' => TRUE,
  );
  $form['mywrapper']['sub'] = array(
    '#type' => 'submit',
    '#value' => t('Save record'),
'#ajax' => array(
      'callback' => 'example_form_submit',
      'wrapper' => 'mywrapper',
    ),
  );
  return $form;
}

function example_form_validate($form, &$form_state) {
if (!valid_email_address($form_state['values']['email'])) {
  form_set_error('email', t('That e-mail address is not valid.'));
}

function example_form_submit($form, &$form_state) {  
  if (!form_get_errors()) {
  <insert data into db>
    $element = $form['mywrapper'];
    $element['#markup'] = "Thank you for contacting us. Someone will be in contact with you shortly.";
  }
  else {    
    $element = $form['mywrapper']; // this must be done, otherwise the form doesn't get rebuilt and no errors are displayed.
  }

return $element;
}

I'm not sure if this is best practice, as I got here with a lot of guess work. If I've done something blackhat, please reply back. Also I haven't tested the code exactly above, but it's basically a toned down version of my fix. Cheers.

maxtorete’s picture

Hi alexkb, thanks for your code. It helps me to submit with ajax and validation my form, and now those fields with validation errors change their color to red, but I can't get the text error displayed on my form.

Have you a solved that issue?

maxtorete’s picture

If I set some wrong values on my form and try to submit it, It doesn't get submited, but after fixed the values with valid ones, it still doesn't get submited.

maxtorete’s picture

My problem was related to the wrapper id used, now it is working fine showing also the errors just before the form.

I was attaching a form to a node with this code on _node_view hook:

		$node->content['mymodyle_myform'] = array(
			'form' => drupal_get_form('mymodule_myform'),
			'#prefix' => '<div id="wrapper">',
			'#suffix' => '</div>',
			'#weight' => 100,
		);

So I was getting an html code like this:

<div id="wrapper"><form>...</form></div>

When the form was submited it used the wrapper div to show the result, so It replaced the form tag with the response without any form tag:

<div id="wrapper">Response</div>

I fixed it setting the prefix and suffix inside the form:


	/**
	* Show a form attached to a node
	*/
	function mymodule_node_view($node, $view_mode) {

		if ($view_mode == 'full' && $node->type == 'mytype') {
			$node->content['mymodule_myform'] = array(
			'form' => drupal_get_form('mymodule_myform', $node),
			'#weight' => 100,
			);
		}

		return $node;
	}

	/**
	 * Define a form.
	 */
	function mymodule_myform($node) {
    
    	$form['myform']['#prefix'] = '<div id="wrapper">';
    	
		$form['myform']['user_name'] = array(
			'#title' => t('Name'),
			'#type' => 'textfield',
			'#description' => t('Please enter your name.'),
		);
		
		$form['myform']['submit'] = array(
			'#type' => 'submit',
			'#ajax' => array(
				'callback' => 'mymodule_myform_submit',
				'wrapper' => 'wrapper',
				'effect' => 'fade',
				'name' => 'submit',
				),
			'#value' => t('Submit'),
		);
		
		$form['myform']['#suffix'] = '</div>';
		
		return $form;
	}

	function mymodule_myform_submit($form, $form_state) {
	    
		$element = $form['myform'];
	    
		if (!form_get_errors()) {
    			$element['#markup'] = "Thank you for contacting us. Someone will be in contact with you shortly.";
		}
				
		return $element;
	}

	/**
	 * Validate the form.
	 */
	function mymodule_myform_validate($form, &$form_state) {
		if ($form_state['values']['user_name'] == 'King Kong') {
			// We notify the form API that this field has failed validation.
			form_set_error('user_name',
				t('King Kong is not allowed to use this form.'));
		}
	}

Thanks to all for your ideas!

Greets.

Fabrice_’s picture

thanks to all

samhassell’s picture

Heres another solution for this problem, without using prefix and suffixes. This is good when you want to replace the form with a message once it has been submitted. It displays the validation messages correctly.

Note that you need to get the id of the form element from the form's HTML output.

function example_ahah_form($form, &$form_state) {
  $form['email'] = array(
    '#type' => 'textfield',
    '#title' => 'Email address',
    '#required' => TRUE,
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t("Submit"),
    '#ajax' => array(
      'callback' => 'example_ahah_form_callback',
      'wrapper' => 'example-ahah-form', // This is taken from the form id in the output.
      'name' => 'submit1',
    ),
  );

  return $form;
}

function example_ahah_form_callback($form, &$form_state) {
  if (form_get_errors()) {
    return $form;
  }

  # Create a new markup field and return it. It will replace the form output.
  $element = array();
  $element['#type'] = 'markup';
  $element['#markup'] = "Thank you for submitting our form!";

  return $element;
}

Also important to note that you should not give your ajax callback function a _submit name (ie. example_ahah_form_submit) - that will cause the function to be triggered twice whenever the ajax form is submitted.

phreestilr’s picture

Thanks for the tip with form_get_errors() !!!

johnish’s picture

This is awesome! I searched the web forever and this is the best example on ajax form submitting!

Thank you thank you!
John