Submit SilverStripe User Forms via AJAX

The User Forms SilverStripe module is super useful for creating forms. I often use it for contact page forms, recently I wanted to submit a contact form via AJAX which is pretty straight forward using SilverStripe's extension class.

Install User Forms module

I won't go through this process in detail, you download the module and put the resulting folder in the root of your SilverStripe installation then run a /dev/build. The module can be found here.

After Installing the module create your contact page and make sure the Page type is a 'User Defined Form'. Then create a basic form for the contact page.

Extend the User Forms module controller

In order to load some javascript which will take care of submitting the contact form via AJAX we need to extend the User Forms' controller. Easily done by creating the class below:

<?php
//mysite/code/UserDefinedFormControllerExtension.php
class UserDefinedFormControllerExtension extends Extension {
 
  /**
   * Add AJAX processing to form
   */
  public function onAfterInit() {
    Requirements::javascript('sapphire/thirdparty/jquery/jquery-packed.js');
    Requirements::javascript($this->owner->ThemeDir() . '/js/libs/jquery.form.js');
    Requirements::javascript($this->owner->ThemeDir() . '/js/UserDefinedForm.js');
  }
 
}

You might want to give the class a better name. Now add the extension by adding the following line to your mysite/_config.php file, then run a dev/build/ for good measure:

//Add AJAX processing to user defined form controller
DataObject::add_extension('UserDefinedForm_Controller', 'UserDefinedFormControllerExtension');

Add the Javascript

The javascript files referenced above do not exist yet, I usually put javascript files in the theme directory in a js/ folder. If the javascript is a library or jQuery extension I will put that into the js/libs/ folder. If you don't follow that convention just make sure your js files are referenced correctly in the Extension class above.

The jQuery form plugin is very useful for submitting forms via AJAX, so you need to download the code and save it as the jquery.form.js file referenced above in the Extension class.

Then we just need to write a quick script to activate the jQuery form plugin for our contact page:

//themes/yourtheme/js/UserDefinedForm.j
jQuery.noConflict();
jQuery(document).ready(function($) { 

	    var options = {
	        target: '#contact_form',
	        success: function() {
	    		$('#Form_Form').ajaxForm(options);
		    }
	    };
	    $('#Form_Form').ajaxForm(options); 

});

Make sure that the target value is correct for your template, this is where the response from the AJAX call is going to be rendered.

Hack the User Forms core

This is obviously the undesirable route, but for now it will get the job done. You *should* be able to overload the method we are about to hack in the Extension class above but it didn't work for me and because I'm in a hurry I just went about hacking. (In my defense I intend to fork the User Forms project in GitHub and see if the core can be changed to facilitate this functionality).

So, just adding the following 3 lines close to the end of the UserDefinedForm_Controller::process() function seemed to work for me, I have included some of the surrounding code starting around about line 757 of the /userforms/code/UserDefinedForm.php file:

	$referrer = (isset($data['Referrer'])) ? '?referrer=' . urlencode($data['Referrer']) : "";

	//Added to render response message if submitted via AJAX
	if (Director::is_ajax()) {
	  return $this->renderWith(array('ReceivedFormSubmission'));
	}

	return Director::redirect($this->Link() . 'finished' . $referrer);
}

Thats about it. As a bonus you can change the AJAX response HTML simply by creating a template in your theme templates/ directory called ReceivedFormSubmission.ss, for an example there is a template of the same name in the userforms/templates/ directory.