Image preview of form here...

Howdy,
I started working with the D7 forms API today, and must say THE API ROCKS!!! I was able to get a basic form going in no time after looking at the examples ajax module.

Challenge: I have a dynamic feedback form on every page that flies in with a click of a button. In page.tpl.php:

<?php print render(drupal_get_form('social_bar_feedback_form')); ?>

It works so far, submitting without refreshing the page! However, if I fail to validate and need to deliver the form again with an error message, I can never get the form to work after that without refreshing the page and starting over. It pretends to submit, then returns the same error(s) no matter what. My guess is some kind of cache or token variable that needs changed?

Here's what I have in my custom module. Any thoughts on where I'm going wrong?

<?php

/**
 * @file
 * Feedback functionality for the "social bar"
 */

//feedback form structure
function social_bar_feedback_form($form, &$form_state) {
	$form['explanation'] = array(
		'#type' => 'markup',
		'#value' => '<div>' . t('We want to hear from you! We look forward to feedback.') . '</div>'
	);
	
	$form['feedback-box'] = array(
		'#type' => 'markup',
		'#prefix' => '<div id="feedback-box">',
		'#suffix' => '</div>',
		'#markup' => '',
	);
	
	$form['first_name'] = array(
		'#type' => 'textfield',
		'#title' => t('First Name'),
		'#size' => 30,
		'#maxlength' => 100,
		'#required' => TRUE
	);
	
	$form['last_name'] = array(
		'#type' => 'textfield',
		'#title' => t('Last Name'),
		'#size' => 30,
		'#maxlength' => 100,
		'#required' => TRUE
	);
	
	$form['email'] = array(
		'#type' => 'textfield',
		'#title' => t('Email Address'),
		'#size' => 60,
		'#maxlength' => 120,
		'#required' => TRUE
	);
	
	$form['feedback'] = array(
		'#type' => 'textarea',
		'#title' => t('Feedback'),
		'#required' => TRUE
	);
	
	$form['submit'] = array(
		'#type' => 'submit',
		'#value' => t('Send Feedback'),
		'#ajax' => array(
			'callback' => 'social_bar_feedback_form_submit',
			'wrapper' => 'social-bar-feedback-form-container',
			'name' => 'submit1',
		),
	); 
	
	$form['alias'] = array(
		'#type' => 'hidden',
		'#value' => social_bar_feedback_url_alias_path()
	);
	
	return $form;
}

//handle form submissions
function social_bar_feedback_form_submit($form, &$form_state) {
	$errors = "";
	$valid = true;
	if(valid_email_address($form_state['values']['email']) == false) {
		$valid = false;
		$errors .= "ERROR: A valid email address is required to send feedback.<br/> ";
	}
	
	if($valid == true) {
		$element = $form['feedback-box'];
		$element['#markup'] = '<div class="messages status">' . t('Thanks for your feedback! Message sent:<br/><br/>
							  First Name: %first_name<br/> 
							  Last Name: %last_name<br/> 
							  Email: %email<br/> 
							  Feedback: %feedback<br/>
							  Sent from: %alias',
			array(
				'%first_name'=>$form_state['values']['first_name'],
				'%last_name' => $form_state['values']['last_name'],
				'%email' => $form_state['values']['email'],
				'%feedback' => $form_state['values']['feedback'],
				'%alias' => $form_state['values']['alias'],
			)) . '</div>';
		return $element;
	} else {
		
		//$form = drupal_prepare_form($form['#build_id'], $form, &$form_state); ?? do I need something like this to allow resubmit?
		
		$form['feedback-box']['#markup'] = '<div class="messages error">' . $errors . '</div>';
		
		return $form;
	}
}

//get current page feedback is being submitted from while buidling the form
//helpful to see where feedback is coming from
function social_bar_feedback_url_alias_path() {
	global $base_path;
	return $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
}

//closing ?> not in actual code...
?>

Thanks for looking! :)

Best regards,

Chris

Comments

owntheweb’s picture

Oh wait....

It looks like it is "working". It's just not updating the display. It says "Thanks for your feedback! Message sent..." in the returned JSON jumble below.

Here's what I can see returning from the ajax call:

[{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"sf_one","theme_token":"S_Rc7khzMg6ZQJlI-3wKVM29ngn3dp7h9i15sy7tcWE","css":[]},"overlay":{"paths":{"admin":"node\/*\/edit\nnode\/*\/delete\nnode\/*\/revisions\nnode\/*\/revisions\/*\/revert\nnode\/*\/revisions\/*\/delete\nnode\/add\nnode\/add\/*\noverlay\/dismiss-message\nuser\/*\/shortcuts\nadmin\nadmin\/*\nbatch\ntaxonomy\/term\/*\/edit\nuser\/*\/cancel\nuser\/*\/edit\nuser\/*\/edit\/*","non_admin":"admin\/structure\/block\/demo\/*\nadmin\/reports\/status\/php"},"ajaxCallback":"overlay-ajax"}},"merge":true},{"command":"insert","method":null,"selector":null,"data":"\u003cdiv id=\"feedback-box\"\u003e\u003cdiv class=\"messages status\"\u003eThanks for your feedback! Message sent:\u003cbr\/\u003e\u003cbr\/\u003e\r\n\t\t\t\t\t\t\t First Name: \u003cem class=\"placeholder\"\u003eChristopher\u003c\/em\u003e\u003cbr\/\u003e \r\n\t\t\t\t\t\t\t Last Name: \u003cem class=\"placeholder\"\u003eStevens\u003c\/em\u003e\u003cbr\/\u003e \r\n\t\t\t\t\t\t\t Email: \u003cem class=\"placeholder\"\u003ecstevens@mywebsite.org\u003c\/em\u003e\u003cbr\/\u003e \r\n\t\t\t\t\t\t\t Feedback: \u003cem class=\"placeholder\"\u003eTest\u003c\/em\u003e\u003cbr\/\u003e\r\n\t\t\t\t\t\t\t Sent from: \u003cem class=\"placeholder\"\u003ewww.roboticast.info\/\u003c\/em\u003e\u003c\/div\u003e\u003c\/div\u003e","settings":null},{"command":"insert","method":"prepend","selector":null,"data":"","settings":null}]

How would I update the display after a failed validation with correct info submitted afterward? This all works fine if there are no validation errors on the first try.

Thanks again,

Chris

Worlds to explore. Worlds to create.
Blog: http://www.christopherstevens.cc/blog
Twitter: http://www.twitter.com/owntheweb

owntheweb’s picture

I got it! It turns out that I was targeting the parent div of the form with id of "social-bar-feedback-form-container" when I should have just focussed on the form id itself of "social-bar-feedback". It's replacing the full target, not just the content within.

All is well. :)

Worlds to explore. Worlds to create.
Blog: http://www.christopherstevens.cc/blog
Twitter: http://www.twitter.com/owntheweb