The Chaos tools form wizard is a very nice piece of code but I had the need to extend it by adding a control button - which turned out to be a lot easier than you might think.
Adding the control button itself was simple enough:
$form['buttons']['update'] = array(
'#type' => 'submit',
'#value' => t('Update'),
'#next' => $current_step,
'#wizard type' => 'update',
'#weight' => -500,
);
But notice I have given this button a wizard type of "update" (as opposed to 'next', 'cancel' or 'finish').
Now you can either add a new line to your $form_info array:
$form_info['update callback'] = 'mywizard_update';
Or not, in which case the function $form_info['id'] . '_update' will be called.
Your function will get called when this button is clicked with &$form_state as the parameter. Cool.
As an additional point, I'm using 'update' here which means that I do want to validate the form entries and save the values. However by adding these element attributes:
'#limit_validation_errors' => array(),
'#submit' => array('ctools_wizard_submit'),
You can prevent all validation and ensure the proper Chaos tools wizard function is executed.
Showing posts with label form wizard. Show all posts
Showing posts with label form wizard. Show all posts
Tuesday, 8 February 2011
Thursday, 27 January 2011
Next and previous
The decision about which page of the multi-page form to go to next is given to the calling code.
You can set up a 'next callback' in $form_info, but not a 'previous callback'. The 'next callback' is called in both cases. The default function name is FORM_ID_next(&$form_state).
In here you control where to go next. The simplest solution is either you want to go to the next, or to the previous. Like this:
<?php
function mywizard_next(&$form_state) {
if (isset($form_state['triggering_element']['#next'])) {
$form_state['my_storage']['step'] = $form_state['triggering_element']['#next'];
}
// set the values built by this page
$form_state['my_storage'][$form_state['step']] = $form_state['values'];
// Update the cache with any changes.
mywizard_cache_set('form_values', $form_state['my_storage']);
}
?>
Why do it like this? Because, being one for elegance and aesthetics, I do not want the current step to appear in the URL (mywizard/step1). I want just the one URL (mywizard). Also notice the use of "triggering_element" which is an addition for Drupal 7, and is identical to "clicked_button". However "clicked_button" will be discontinued in Drupal 8.
The Chaos Tools form wizard needs you to build the $form_info array and call its function 'ctools_wizard_multistep_form' each time the page is to be rebuilt. So, in my function that gets called for the page I do some interesting things.
<?php
function mywizard_wizard() {
ctools_include('wizard');
// Fetch the form info array
$form_info = mywizard_form_info();
// Fetch the current form values from the cache...
$form_values = mywizard_cache_get('form_values');
if (empty($form_values)) {
// ...but if they aren't there, build the initial values
$form_values = array(
// set the first step
'step' => array_shift(array_keys($form_info['order'])),
// and my default start values (if any)
'mywizard_values' => array(),
);
mywizard_cache_set('form_values', $form_values);
}
// Build $form_state array
$form_state = array(
'my_storage' => $form_values,
);
// And build the current step
return ctools_wizard_multistep_form($form_info, $form_values['step'], $form_state);
}
?>
So, if you can follow this, when we enter the function we build the $form_info array which describes the whole multi-page form. If this was a complicated process (it could be) you could also cache the $form_info array so it only needs to be done once.
Then we either fetch the cached form data, which contains the next step, or build a new one if we don't have one (in other words this is the first time through).
We save this information in $form_state and then call the ctools multi-step form builder which finds the right form and builds it.
When "next" is clicked (or "back") we save the current step and cache it. To be picked up when the page is built next time.
Voila.
Edited later to remove some unnecessarily complex code. This should be viewed in conjunction with the Chaos Tools Advanced Help.
No back validate
Here's an undocumented option for your Chaos Tools form wizard (not sure if it's in the D6 code): 'no back validate'.
It prevents validation of the current form when you click the back button which means you can use #required fields and prevent Drupal from insisting the user fills them in before going back through the form.
You can either put it in the root level of the $form_info array, or in one or more of the form description entries. The former means that the back button will always prevent validation, with the latter you can control which forms do and don't have validation on the back button.
Handy.
Subscribe to:
Posts (Atom)