1

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;
}
  • have you tried instead of using '#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 – Marius Ilie May 8 '12 at 10:01
  • @MariusIlie thanks this exactly what I was looking for! Please add your comment as an answer so I can +1 it and close the loop for others. Thanks again, this was a stumper! – Jerrud May 8 '12 at 13:41
  • I added the comment as an answer. Cheers :) – Marius Ilie May 8 '12 at 15:30
1

have you tried instead of using '#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

0

You can try this!!

$form['--Name--'] = array(

         '#type' => 'managed_file',

        '#name' => 'files[]',

        '#title' => t('Upload some multifile'),

        '#description' => t('Allow to upload jpg, jpeg and png, 5MB Max Size'),

        '#attributes' => array('multiple' => 'multiple'),

  );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.