Hello,

I would like to know if it was possible in Drupal 6 to do a multistep form using hook_form ? There is a node type that I have defined, so I would like to use hook_form to display the node editing form, but I want to add other informations that have to be stored in another table and that need to use a multistep form. The problem is that all documentation I have found on multistep form say that I have to use $form_state, the first parameter of the function that generate the form, but the fact is that the first parameter of hook_form is &$node, so how can I do ?
Thanks for your help !

Jeff

Comments

teyser’s picture

Hi,
Send your mail id

Thanks,
Raj.

jfberroyer’s picture

It seems that the poll module in drupal core uses such a multistep node form. I'm gonna see in the code how it works.

The $form_state is passed as second parameter to the hook form of which prototype, line 184, is:
function poll_form(&$node, $form_state) { ...

twom’s picture

Hy,

I have created a simple example illustrating a multistep node creation form. The code defines a node type 'test' (don't forget the info file), that is created in two steps. I use the devel module to output some variables, to illustrate where in the form 'lifecycle' we are.

It seems to work for me. Let me know if this is working for you or if you would suggest some better examples.

UPDATE (4/08): I have added a check in the form alter in order to only do the altering for the test form.

<?php

/**
 *  Implementation of hook_info()
 */ 
function test_node_info() {
  return array(
    'test' => array(
      'name' => t('Test content'),
      'module' => 'test',
      'description' => t('Creating test content'),
      'has_title' => TRUE,
      'title_label' => t('Test title'),
      'has_body' => TRUE,
      'body_label' => t('OVerview'),
    )
  );
}

/**
 * Implementation of hook_form()
 * 
 * This function will be called twice. The first time $node and $form_state will be almost empty
 * The second time, $node->step will be set to one, and $form_state wil contain the $form_state['values']['test1'] element. 
 */     
function test_form(&$node, $form_state) {
  //check if it is the first time that the form is called
  // If not, increase step with one.
  if (count($form_state['values']['step']) == 0 ) {
    $step = 1;
  } else {
    $step = $form_state['values']['step'] + 1;
  }
  dpm('step ' . $step);
  // Set a hidden field that keeps the current step
  $form['step'] = array (
    '#type' => 'hidden',
    '#value' => $step
  );
  
  // build the form, based on the step
  
  switch ($step) {
    case '1':
    $form['test1'] = array(
    '#type' => 'textfield',
    '#title' => 'step 1',
    '#rows' => 1
   );
   break;
   case '2':
   $form['test2'] = array(
    '#type' => 'textfield',
    '#title' => 'step 2'
   );
   // keep the value of form one as a hidden form value
  $form['test1'] = array(
    '#type' => 'hidden',
    '#value' => $form_state['values']['test1']
  );
   break;
  }
  return $form;
}

/**
 * Implementation hook_validate()
 */ 
function test_validate($node) {
  dpm('validate');  
}

/**
 * Here we disable in step 1 the submit button. In step 2 we disable the preview button*/
function test_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'test_node_form' ) {
  if ($form['step']['#value'] < 2) {
   $form['#rebuild'] = TRUE;
    unset($form['buttons']['submit']);
    $form['buttons']['preview']['#value'] = t('Next');
  } else {
    $form['#rebuild'] = FALSE;
    $form['#redirect'] = TRUE;
    unset($form['buttons']['preview']);
  }
}
}

/**
 * We can do some database savings here
 */ 
function test_insert($node) {
  dpm('insert');
  dpm($node->test1 . " | " . $node->test2); 
}

vvchik’s picture

Great! works perfectly!
But one question if I want make a some file field in first step how to save it?