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: