The Webform module is wonderful. It provides us a quick and easy way to add forms to our site, and takes care of the form handling. And, it’s all done through an easy to use GUI. With the release of Drupal 7, the Form API got tweaked a bit. More specifically, the AJAX handling of forms is now quite a bit more straight ahead. I recently had a site build where I needed a contact form to be submitted using AJAX. A confirmation message would replace the form after a successful submission. Unfortunately, there’s no release of the Webform Ajax module for Drupal 7, so I had 2 choices: 1) Use the Form API, write my own form validations and submit handling to store submissions in the database and send emails out, or 2) use the Webform module and alter it to use AJAX. From the title of this blog, you know that the latter was the winner. Let’s get started.
Create the Webform
I’ve already downloaded and enabled the Webform module, and created a simple contact form:

Add the confirmation message
Now we need to enter the confirmation message on the Form settings page (node/[your node id]/webform/configure). Fill in the Confirmation message field, then select the Confirmation page option under the Redirection location setting.

Alter the Webform
We’re going to use hook_form_alter so we can add the AJAX form handler to our Webform.
function sandbox_form_alter(&$form, &$form_state, $form_id) {
if(strstr($form_id, 'webform_client_form_')) {
$nid = $form['#node']->nid;
$form['actions']['submit']['#ajax'] = array(
'callback' => 'sandbox_webform_js_submit',
'wrapper' => 'webform-client-form-' . $nid,
'method' => 'replace',
'effect' => 'fade',
);
}
}
Let’s go through it line by line:
if(strstr($form_id, 'webform_client_form_')) {
Here we’re using the strstr PHP function to check and see if webform_client_form_ is in the $form_id. This allows us to alter all of the Webform module‘s forms.
$nid = $form['#node']->nid;
We need to store the node id so we can use it in the AJAX wrapper parameter below.
$form['actions']['submit']['#ajax'] = array(
Using a print_r (or dsm will also work) of the $form array, I was able to find the submit button values. We need to add the #ajax array to it so Drupal will submit using AJAX if we are serving a JavaScript enabled browser.
'callback' => 'sandbox_webform_js_submit',
The callback parameter defines the callback function to use for the AJAX submit. We will write that function next.
'wrapper' => 'webform-client-form-' . $nid,
The wrapper parameter defines the element id that will be affected by what is returned by the callback function. In our case we are going to replace the entire form with the confirmation message, so our wrapper is the id of the Webform itself.
'method' => 'replace',
The method parameter defines what we do to the wrapper. We are using replace, but we could also use ‘after’, ‘append’, ‘before’, or ‘prepend’. Check out the Form API Reference for more infor on how those methods can be used.
'effect' => 'fade',
The effect parameter defines what affect the method will have on the wrapper. We are using fade, but we could also use ‘none’ or ‘slide’.
Write the AJAX handler callback function
Now we need to create the sandbox_webform_js_submit callback function that we defined above in the #ajax array:
function sandbox_webform_js_submit($form, $form_state) {
$sid = $form_state['values']['details']['sid'];
if ($sid) {
$node = node_load($form_state['values']['details']['nid']);
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
);
return $confirmation;
}
else {
return $form;
}
}
And line by line:
$sid = $form_state['values']['details']['sid'];
if ($sid) {
First we define the $sid variable, so we can check to see if the form was properly submitted. If we have a successful submission, we will replace the form with the confirmation message. Otherwise, we will return the $form array, which will include the error messages.
$node = node_load($form_state['values']['details']['nid']);
We need to load up the Webform node so we can get the confirmation message that we entered earlier through the UI.
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
);
return $confirmation;
}
We need to create a render array with markup in it. We are using the type of markup and we’re pulling the confirmation directly from the $node object.
else {
return $form;
}
This is the else that indicates we do not have a form submission. We simply return the $form array.
Put it all together
function sandbox_form_alter(&$form, &$form_state, $form_id) {
// see if webform_client_form_ is in the form_id
if(strstr($form_id, 'webform_client_form_')) {
// get the nid so we can use it in the wrapper value
$nid = $form['#node']->nid;
// add the ajax properties to the submit button
$form['actions']['submit']['#ajax'] = array(
'callback' => 'sandbox_webform_js_submit',
'wrapper' => 'webform-client-form-' . $nid,
'method' => 'replace',
'effect' => 'fade',
);
}
}
function sandbox_webform_js_submit($form, $form_state) {
// define the $sid variable (submission id from webform)
$sid = $form_state['values']['details']['sid'];
// if we have a sid then we know the form was properly submitted, otherwise, we'll just return the existing $form array
if ($sid) {
// first we have to load up the webform node object
$node = node_load($form_state['values']['details']['nid']);
// create an array up with the confirmation message, retreived from the webform node
$confirmation = array(
'#type' => 'markup',
'#markup' => check_markup($node->webform['confirmation'], $node->webform['confirmation_format'], '', TRUE),
);
// return the confirmation message
return $confirmation;
}
else {
// return the form
return $form;
}
}
Success!
Now, after submitting my Webform, I get my confirmation without a page refresh:


August 15th, 2011 at 4:14 pm
This is just what i have been looking for, but i don’t see where should i use this code. im new to drupal as you can guess. i tryed it in webform-form-tpl.php but didnĀ“t seem to work
Thank you for your help
August 15th, 2011 at 4:54 pm
You’ll need to create a custom module to hold this code. Basically, you’ll need to create a folder in the /sites/all/modules directory and call it the name of your module. In the example above I called my module sandbox. Inside that folder you will need to create 2 files: sandbox.info and sandbox.module. In the sandbox.module file, put the opening php tag on the first line (<?php) then paste the 2 functions from the example. Next, in the sandbox.info file, use the following code:
name = Sandbox
description = Provides custom functionality for the Sandbox.
core = 7.x
; Information added by drupal.org packaging script on 2011-06-16
version = "7.x-1.0"
core = "7.x"
project = "sandbox"
datestamp = "1308241021"
Once those 2 files are saved, visit the admin/config/development/performance page and hit the Clear all caches button. Go to the admin/modules page and enable the Sandbox module. You should be good to go after that.
For more info on creating custom modules, check out this post on Drupal.org: http://drupal.org/node/1074362
Hope that helps! Thanks for checking out the blog,
mark
August 16th, 2011 at 11:26 am
HUGE, thank you. You’ve got me both on the road to custom mod. development and helped me solve an immediate need. VERY helpful thanks. For anyone else reading this, you don’t have to change a single line of code although my AJAX submit didn’t work with any complex fields (grids) in the Webform module. So I stuck with simple text fields.
August 16th, 2011 at 11:32 am
No problem at all! You can definitely add some more robust code to handle the complex fields. Experiment with it and check out the dsm function from the devel module. It will print array contents to the screen so you can see the values. I also us this line of code to check out the contents of arrays and variables:
drupal_set_message(”.print_r($my_variable_or_array,TRUE).”);
Both are invaluable tools when learning to alter drupal data.
August 19th, 2011 at 10:54 am
Thank you so much! This was exactly what I was looking for!
August 23rd, 2011 at 9:24 am
Sounds good, I’ll play with it when there’s more time. In the short term, if you have a minute can you see if this error message clarifies things? http://sensorclouds.com/contact-us “The page at http://sensorclouds.com says:
An AJAX HTTP request terminated abnormally.
Debugging information follows.
Path: /system/ajax
StatusText: n/a
ResponseText: This server is experiencing technical problems. Please
try again in a few moments. Thanks for your continued patience, and
we’re sorry for any inconvenience this may cause.
Error 503 Service Unavailable
Service Unavailable
XID: 1804996970
ReadyState: undefined”
August 23rd, 2011 at 9:36 am
Hey Scott! It looks like there might be a problem in the AJAX submit function (in the example above it’s called sandbox_webform_js_submit). What I would suggest doing, is walking through that function line by line and returning some of the values, until you find the line of code that is causing the error. To do this, start with:
return “hello world!”;
as the first line of the function. Hopefully that will replace your form with the hello world! text. If that is successful, move down below the line that defines the $sid variable and add this line:
return $sid;
Continue going through line by line until you locate the problem. Hopefully that helps!
August 29th, 2011 at 8:03 pm
Very helpful post and valuable comments, thank you.
Did anyone work it for the complex fields?
And there is something more, validation modules (Clientside Validation, Webform Validation..) won’t display required information after applying the code above. The fields just get red and that it.
Does somebody know a solution to that?
September 18th, 2011 at 3:26 am
Thank you very much Mark. You really saved me. I am new to Drupal..
How did you figured it out how to do something like that? I can do ajax with my custom forms but with Webform is very different think…
November 18th, 2011 at 12:30 am
This post is fantastic! One problem I’ve encountered – if you’re using a Date component, it throws back this error message – “Fatal error: Call to undefined function webform_expand_date() “. Any idea why this might be happening, and how to get around it?
December 3rd, 2011 at 1:13 am
Hi Marc (and others). I have added a comment to this issue on Drupal.org. Should address everyone’s problem with various “complex” components (components requiring expand functionality).
http://drupal.org/node/1091354#comment-5319708
December 11th, 2011 at 6:53 pm
I run the webform in a block, and it worked almost perfectly for me.
How would go to the confirmation message and then five seconds back to the contact form?
December 16th, 2011 at 11:45 am
[...] used the steps outlined at http://envisioninteractive.com/drupal/add-ajax-to-a-webform-in-drupal-7/ which works well, except for these few issues. This entry was posted in drupal and tagged ajax by [...]
February 27th, 2012 at 9:20 am
Just a quick note to say thanks for putting up this code for AJAXifiying webforms! It was exactly what I was looking for and has totally made my Monday morning.
March 16th, 2012 at 6:13 am
Hello!
For me it works as long as I access the webform on it’s own node.
But then the form in a block then… even tho’ I can see (print_r) that the alter function does it’s job, there is no AJAX on the actual form.
Anybody has an idea?
Thanks,
March 16th, 2012 at 6:37 am
Never mind. Got it fixed.
September 26th, 2012 at 12:42 am
Great post! Thanks for sharing! Just what I was looking for.
November 11th, 2012 at 9:23 am
Just wanted to say thank you for such a helpful post. This has saved me a lot of time and I’ve learned a lot too. It’s people like you who make the web go around. Brilliant!
February 8th, 2013 at 10:02 pm
Thanks Mark, I just want to say that now the Webform Ajax module (http://drupal.org/project/webform_ajax) is working for D7.