Simple Ajax form with jQuery

A simple AJAX form with jQuery

This is a very basic 'hello-worldish' example of a Form that lets you enter a name and then returns with a greeting. If JavaScript is enabled, we'll use AJAX, if not, we'll accomplish the same effect the oldfasioned way. We'll create a new AJAXFormPage that has the following controller functions:

  • AjaxForm() - builds the actual form
  • doSubmit() - saves the posted name in a session cookie and redirects back to the page
  • FormResult() - retrieves the name from the session cookie for display on the page

AJAXFormPage

We'll start by creating the page without any AJAX functionality

/mysite/AjaxFormPage.php

class AjaxFormPage extends Page {
}
class AjaxFormPage_Controller extends Page_Controller {

	// create the form
	function AjaxForm() {

		if ($this->ID <= 0) return false;

		$fields = new FieldSet(
			new TextField('Name', 'Name:'),
			new HiddenField('Page', 'Page', $this->ID)
		);

		$actions = new FieldSet(
			new FormAction('doSubmit', 'submit') 
		);
		return new Form($this, 'AjaxForm', $fields, $actions);
	}



	// handle the submitted (non-AJAX) Form
	function doSubmit($postedData, $form) {

		// do all kinds of stuff with the posted data

		$name = Convert::raw2xml($postedData['Name']);
		Session::set('formresults', $name);
		Director::redirectBack();
	}



	// return the non-AJAX results from the session cookie
	function FormResult() {
		$name = Session::get('formresults');
		if(!empty($name)) { 
			Session::clear('formresults'); 
			return 'Hi ' . $name;
		}
		return false;
	}
}

The Template


The template is very simple. Somewhere in themes/.../Layout/Page.ss add the following (and do a ?flush=1):

<div id="result">$FormResult</div>
$AjaxForm

Add AJAX to the form

Next we'll add a new AJAXSubmit() method to the form, that will handle AJAX request. In this example we're not really going to submit the form. Instead, we'll  serialize the formvalues and post them to the page, targeting the AJAXSubmit() method. This can simply be done by adding AJAXSubmit to the end of the url.

So first the init() method: load the jQuery library, and create a bit of JavaScript code that will do the following:

  • add AJAXSubmit to the end of the url
  • serialize the form values en post them along with the url
  • load the response into the div with id="result" (overwiting what's already in there)
	function init() {
		parent::init();

		// load jQuery
		Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
    
		$ajaxLoad = $this->Link() . 'AJAXSubmit';	
  
		// respond to form submission 
		$url = $this->Link() . 'AJAXSubmit';	

		Requirements::customScript(<<<JS
			(function($) {
				$(document).ready(function() {
	
					$("#Form_AjaxForm").submit(function(){
						$('#result').load(
							'{$url}',
							{values: $(this).serialize()}
						);
						return false;
					});
				});
  	    		})(jQuery);
JS
    		);
	}

The AjaxSubmit() function

Next we need to add the AJAXSubmit method to the AjaxFormPage_Controller and we're basically ready:

function AjaxSubmit() {
	if (Director::is_ajax()) {
		parse_str(urldecode($this->requestParams['values']), $postedData);
		if ($postedData['SecurityID'] == Session::get('SecurityID')) {
			return 'Hi ' . Convert::raw2xml($postedData['Name']);
		}
		else return false;
	}
	return array();
}

@TODO

Although this method should normally only be called by AJAX, I'm still checking. If for some reason the AJAX url is called directly, I want the page to be rendered normally, which the 'return array()' bit will do for me. The other thing I do is check the forms securityID against the one saved in the session. (Is this necessary? Does it make sense?). That's about it.

Things to consider

  • Validate all user input
  • There are numous other ways to tackle AJAX, this is a very simple way
  • Create methods for use with AJAX and non-AJAX submits, if you want the same things to be done

...Musings...

When submitting the non-ajax form,  'AjaxForm' is added to the url, so the form can be rebuilt on submit. This could work for AJAX submits as well, only the SecurityID makes this difficult: it won't match, resulting in a 400 response code (see Firebug). You can disable the securityID for the form, but I'm not happy about that. Next you still have to divide the doSubmit method in an AJAX and a non_AJAX part. The nice thing about this would be that AJAX submits would also have $form and &postedData at their disposal. The drawback is that you'd have to change the way you AJAX-POST the data to have $postedData be the same on both submits...

Comments

Het versturen van reacties is uitgeschakeld.

RSS feed voor reacties op deze pagina