I know this question is a bit old, but might help someone in the same situation as I was.
If you end up creating custom submit handlers and having to take care of saving the step values manually then you are not fully taking advantage of what ctools has to offer.
The documentation on using and creating multi step forms is quite poor, but following this blog post helped me understand better all the different callbacks that the ctools wizard offers:
http://www.grasmash.com/article/building-multistep-registration-form-drupal-7-using-ctools
The only thing missing from the 'next callback' in that tutorial is 'merging' the existing values from the cache with the new ones from your current step (see below).
When you define your '$form_info' and specify all the ctools steps and options, you have the ability to set callback for 'next', 'finish', 'return', and 'cancel' actions.
The way I ended up saving my step data when going back and forward is by setting the 'next callback' and then saving the $form_state['values']
in the ctools object cache.
'next callback' => 'my_module_subtask_next',
Then in the actual callback function you basically merge your current cached object with the new $form_state['values']:
function my_module_subtask_next(&$form_state) {
$values = (array) my_module_get_page_cache('my_module');
my_module_set_page_cache('my_module', array_merge($values, $form_state['values']));
}
Then when setting up your $form fields you can retrieve this ctools cache object and set your #default_value
:
// ctools automatically adds the cache object in your $form_state
$form_values = $form_state['my_module_object'];
$form['example'] = array(
'#type' => 'texfield',
'#title' => t('Example field'),
'#default_value' => (isset($form_values['example'])) ? $form_values['example'] : NULL,,
);