Create Custom Multistep Form Using Ajax

Multistep Form Using Ajax

Don't want long forms on your website? Convert it into multi-step form, as it is more convenient and provides step by step procedure to follow by user. This blog will provide a way to create of multi step form using ajax.
                   
1. Create a menu item using hook_menu()

/**
* Implementation of hook_menu().
*/
function custom_menu() {
$menu['multistep_form'] = array
(
'title' => 'Multistep Form',
'description' => 'To create multistep form',
'page callback' => 'drupal_get_form',
'page arguments' => array('ajax_multistep_form'),
'access callback' => TRUE,
);
return $menu;
}

 

2. Define a callback function
 
It includes stepwise fields. It contains fieldset for each step with their respective fields. Then It will includes buttons for each step. We have called ajax_multistep_form_ajax_callback function it returns the entire form each time the function is called. Added a wrapper div “ajax_multistep_form'” to update the form using AJAX.

$form['buttons']['next'] = array
(
'#type' => 'submit',
'#value' => t('Next'),
'#ajax' => array
(
'wrapper' => 'ajax_multistep_form',
'callback' => 'ajax_multistep_form_ajax_callback',
),
);

 

Multistep Form Using Ajax
Multistep Form Using Ajax
Multistep Form Using Ajax
function ajax_multistep_form($form, &$form_state)
{
 
// If $form_state['step'] is not set then set default to 1
$form_state['step'] = isset($form_state['step']) ? $form_state['step'] : 1;
// Add a wrapper div to update the form using AJAX
$form['#prefix'] = '<div id="ajax_multistep_form">';
$form['#suffix'] = '</div>';
 
switch($form_state['step'])
{
// Step 1
case 1:
$fname_default_value = $lname_default_value = '';
if(isset($form_state['values']['step_1']))
{
$fname_default_value = $form_state['values']['step_1']['fname'];
$lname_default_value = $form_state['values']['step_1']['lname'];
}
elseif(isset($form_state['storage']['step_1']))
{
$fname_default_value = $form_state['storage']['step_1']['fname'];
$lname_default_value = $form_state['storage']['step_1']['lname'];
}
 
$form['step_1'] = array(
'#type' => 'fieldset',
'#title' => t(''),
'#collapsible' => false,
'#collapsed' => false,
);
$form['step_1']['fname'] = array(
'#type'=>'textfield',
'#required' => true,
'#title'=>t('First Name'),
'#default_value' => $fname_default_value,
);
$form['step_1']['lname'] = array(
'#type'=>'textfield',
'#required' => true,
'#title'=>t('Last name'),
'#default_value' => $lname_default_value,
);
break;
// Step 2
case 2:
$phone_default_value = '';
if(isset($form_state['values']['step_2']))
{
$phone_default_value = $form_state['values']['step_2']['phone'];
}
elseif(isset($form_state['storage']['step_2']))
{
$phone_default_value = $form_state['storage']['step_2']['phone'];
}
 
$form['step_2'] = array(
'#type' => 'fieldset',
'#title' => t(''),
'#collapsible' => false,
'#collapsed' => false,
);
$form['step_2']['phone'] = array(
'#type'=>'textfield',
'#required' => true,
'#title'=>t('Phone Number'),
'#default_value' => $phone_default_value,
);
break;
// Step 3
case 3:
$city_default_value = $city_default_value = '';
if(isset($form_state['values']['step_3']))
{
$street_default_value = $form_state['values']['step_3']['street'];
$city_default_value = $form_state['values']['step_3']['city'];
}
elseif(isset($form_state['storage']['step_3']))
{
$street_default_value = $form_state['storage']['step_3']['street'];
$city_default_value = $form_state['storage']['step_3']['city'];
}
 
$form['step_3'] = array(
'#type' => 'fieldset',
'#title' => t(''),
'#collapsible' => false,
'#collapsed' => false,
);
$form['step_3']['street'] = array(
'#type'=>'textfield',
'#required' => true,
'#title'=>t('Street Address'),
'#default_value' => $street_default_value,
);
 
$form['step_3']['city'] = array(
'#type'=>'textfield',
'#required' => true,
'#title'=>t('City'),
'#default_value' => $city_default_value,
);
 
}
 
 
// Form Buttons
$form['buttons'] = array
(
'#type' => 'container',
);
// If we are on step 1, we do not want a back button
if($form_state['step'] !== 1)
{
$form['buttons']['back'] = array
(
'#type' => 'submit',
'#value' => t('Back'),
'#limit_validation_errors' => array(),
'#submit' => array('ajax_multistep_form_back_submit'),
'#ajax' => array
(
'wrapper' => 'ajax_multistep_form',
'callback' => 'ajax_multistep_form_ajax_callback',
),
);
}
 
if($form_state['step'] !== 3)
{
$form['buttons']['next'] = array
(
'#type' => 'submit',
'#value' => t('Next'),
'#ajax' => array
(
'wrapper' => 'ajax_multistep_form',
'callback' => 'ajax_multistep_form_ajax_callback',
),
);
}
else
{
$form['buttons']['submit'] = array
(
'#type' => 'submit',
'#value' => t('Submit'),
'#ajax' => array
(
'wrapper' => 'ajax_multistep_form',
'callback' => 'ajax_multistep_form_ajax_callback',
),
);
}
return $form;
}

 

3. Add validation for your fields
 
It will add validation for phone number field in step 2. You can add validations for other steps too.

Multistep Form Using Ajax
function ajax_multistep_form_validate($form, &$form_state) {
switch($form_state['step'])
{
case "2":
$contact_phone = $form_state['values']['phone'];
$contact_errror = '"'.$contact_phone .'"' . ' is not a valid North American phone number. Please enter a valid ten-digit phone number with optional extension in this format 123 456 7891.';
if (!preg_match('/([0-9]{3}?\s?[0-9]{3}?\s?[0-9]{4})/', $contact_phone)) {
form_set_error('phone', $contact_errror);
}
break;
}
}

 

4. Final submit function

function ajax_multistep_form_submit($form, &$form_state) {
 
$step = $form_state['step'];
 
//$form_state['storage']['step_' . $step] = $form_state['step'];
 
if($form_state['step'] == 1) {
$form_state['storage']['step_' . $step]['fname'] = $form_state['values']['fname'];
$form_state['storage']['step_' . $step]['lname'] = $form_state['values']['lname'];
 
}
if($form_state['step'] == 2) {
$form_state['storage']['step_' . $step]['phone'] = $form_state['values']['phone'];
}
 
if(isset($form_state['values']['next']) && $form_state['values']['op'] == $form_state['values']['next'])
{
// Goto next step
$form_state['step']++;
}
 
if(isset($form_state['values']['back']) && $form_state['values']['op'] == $form_state['values']['back'])
{
// Goto next step
$form_state['step']--;
}
// Check if it is last step
elseif(isset($form_state['values']['submit']) && $form_state['values']['op'] == $form_state['values']['submit'])
{
 
$form_state['storage']['step_' . $step]['street'] = $form_state['values']['street'];
$form_state['storage']['step_' . $step]['city'] = $form_state['values']['city'];
 
$items = array($form_state['storage']['step_1']['fname'], $form_state['storage']['step_1']['lname'], $form_state['storage']['step_2']['phone'], $form_state['storage']['step_3']['street'], $form_state['storage']['step_3']['city']);
drupal_set_message(t('You submitted the following values:!values', array('!values' => theme('item_list', array('items' => $items)))));
 
$form_state['step'] = 1;
$form_state['storage'] = array();
}
$form_state['rebuild'] = TRUE;
}

 

5. Ajax callback function for every buttons in our form

function ajax_multistep_form_ajax_callback($form, &$form_state)
{
return $form;
}

 

This it just an example, you store all steps value in “$form_state['storage']” and use it.

$step = $form_state['step'];
$form_state['storage']['step_' . $step]['values'] = $form_state['values'];

 

Hope this helped you to get most out of the system. Feel free to share your reviews or need assistance regarding our CakePHP development services then get in touch with us. #WeDrupalEveryday. Pick the best answer for your requirements.