How can I save a file using file_save_upload in a AJAX multistep form? This works for a simple form, but I'm not sure where I'm going wrong in the multistep. Any help is very much appreciated!
File save works in simple form:
function xmlimport_form_submit($form, &$form_state){
$validators = array('file_validate_extensions' => array());
$file = file_save_upload('fid', $validators,'public://',FILE_EXISTS_RENAME);
}
But doesn't seem to work in multistep. The error I get in my block says, "No file chosen" when I click Next Step on my form. AJAX form taken from Form API Example module.
function xmlimport_wizard($form, &$form_state) {
$form['#prefix'] = '<div id="wizard-form-wrapper">';
$form['#suffix'] = '</div>';
$form['#tree'] = TRUE; // We want to deal with hierarchical form values.
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
$form_state['storage']['step'] = $step;
switch ($step) {
case 1:
$form['step1'] = array(
'#type' => 'fieldset',
'#title' => t('Step 1: Log RFI from XML'),
);
$form['step1']['fid'] = array(
'#type' => 'file',
'#title' => t('Your XML file'),
'#default_value' => empty($form_state['values']['step1']['fid']) ? '' : $form_state['values']['step1']['fid'],
'#required' => TRUE,
);
break;
case 2:
$form['step2'] = array(
'#type' => 'fieldset',
'#title' => t('Step 2: Street address info'),
);
$form['step2']['project'] = array(
'#type' => 'textfield',
'#title' => t('Project Name'),
'#default_value' => empty($form_state['values']['step2']['project']) ? '' : $form_state['values']['step2']['project'],
'#required' => TRUE,
'#size' => 23,
);
break;
}
if ($step == 2) {
$form['submit'] = array(
'#type' => 'submit',
'#value' => t("Submit your information"),
);
}
if ($step < 2) {
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Next step'),
'#ajax' => array(
'wrapper' => 'wizard-form-wrapper',
'callback' => 'xmlimport_wizard_callback',
),
);
}
if ($step > 1) {
$form['prev'] = array(
'#type' => 'submit',
'#value' => t("Previous step"),
// Since all info will be discarded, don't validate on 'prev'.
'#limit_validation_errors' => array(),
// #submit is required to use #limit_validation_errors
'#submit' => array('xmlimport_wizard_submit'),
'#ajax' => array(
'wrapper' => 'wizard-form-wrapper',
'callback' => 'xmlimport_wizard_callback',
),
);
}
return $form;
}
function xmlimport_wizard_callback($form, $form_state) {
$validators = array('file_validate_extensions' => array());
$file = file_save_upload('fid', $validators,'public://',FILE_EXISTS_RENAME);
return $form;
}
/**
* Submit function for xmlimport_wizard.
*
* In AJAX this is only submitted when the final submit button is clicked,
* but in the non-javascript situation, it is submitted with every
* button click.
*/
function xmlimport_wizard_submit($form, &$form_state) {
// Save away the current information.
$current_step = 'step' . $form_state['storage']['step'];
if (!empty($form_state['values'][$current_step])) {
$form_state['storage']['values'][$current_step] = $form_state['values'][$current_step];
}
// Increment or decrement the step as needed. Recover values if they exist.
if ($form_state['triggering_element']['#value'] == t('Next step')) {
$form_state['storage']['step']++;
// If values have already been entered for this step, recover them from
// $form_state['storage'] to pre-populate them.
$step_name = 'step' . $form_state['storage']['step'];
if (!empty($form_state['storage']['values'][$step_name])) {
$form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
}
}
if ($form_state['triggering_element']['#value'] == t('Previous step')) {
$form_state['storage']['step']--;
// Recover our values from $form_state['storage'] to pre-populate them.
$step_name = 'step' . $form_state['storage']['step'];
$form_state['values'][$step_name] = $form_state['storage']['values'][$step_name];
}
// If they're done, submit.
if ($form_state['triggering_element']['#value'] == t('Submit your information')) {
$value_message = t('Your information has been submitted:') . ' ';
foreach ($form_state['storage']['values'] as $step => $values) {
$value_message .= "$step: ";
foreach ($values as $key => $value) {
$value_message .= "$key=$value, ";
}
}
drupal_set_message($value_message);
$form_state['rebuild'] = FALSE;
return;
}
// Otherwise, we still have work to do.
$form_state['rebuild'] = TRUE;
}
'#type' => 'file'
for your file upload field to use the'#type' => 'managed_file'
? it's easier to validate and it's ajax enabled by default. You can read more about it here