by Jeff Eaton on November 22, 2006 // Short URL

Drupal 5: Making forms that display their own results

Drupal's Form API offers advanced features for validation, processing, and (in version 5) multi-part forms that span several pages. Sometimes, though, you need to do something simple: write a form that does nothing but display some formatted information based on the data that was submitted.

Here's a short snippet of code that demonstrates how Drupal 5's new #multistep flag (used for complex, multi-page forms) can also simplify the little problems.

function multistep_example_form($form_values = NULL) {
$form = array();
// Setting #multistep to true activates some special form
  // handling code for Drupal. First, the FormAPI makes sure
  // that the results of the form's submission are passed back
  // into the builder function when the page loads for the second
  // time. That gives it a chance to build a different version of
  // the form (with additional options, for example). It also
  // does magickal voodoo that keeps validation working properly
  // in those complex multi-page forms. For now, we won't
  // worry about that.
$form['#multistep'] = TRUE;
// Setting #redirect to false means that Drupal *won't* attempt
  // to reload a clean copy of the form (by redirecting to the
  // current page, and reloading) when it's submitted. In a multistep
  // form, we want to keep the data around so it can be displayed,
  // or passed on to a subsequent step.
$form['#redirect'] = FALSE;
// Remember: in a #multistep form, Drupal makes sure that the
  // $form_values array is passed into this builder function once
  // you submit the form. That gives us a chance to display different
  // form fields based on what was previously submitted.
if ($form_values === NULL) {
// We're entering the form for the first time. Display the form!
$form['text'] = array(
'#type' => 'textfield',
'#title' => t('Text field'),
'#required' => TRUE,
$form['more_text'] = array(
'#type' => 'textarea',
'#title' => t('A bigger text field'),
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
  else {
// $form_values is populated, which means we're coming in a second
    // time. Let's display the results instead of the original form fields.
$form['results'] = array(
'#type' => 'item',
'#title' => t('The results of your form submission'),
'#value' => _multistep_example_format_values($form_values),
_multistep_example_format_values($form_values = array()) {
$header = array(t('Key'), t('Value'));
$rows = array();
  foreach (
$form_values as $key => $value) {
$row = array();
$row[] = $key;
$row[] = check_plain($value);
$rows[] = $row;
theme('table', $header, $rows);

That's all there is to it! Obviously, most modules will need to do some more complex formatting than that when they display their results. But the skeleton is there, and should serve you well.

Jeff Eaton

Senior Digital Strategist

Want Jeff Eaton to speak at your event? Contact us with the details and we’ll be in touch soon.



What about form_alter?

Your example assumes your are building a node module (e.g. hook_form).

How would (or would) this need to be modified to work on a module that was extending a node via hook_form_alter?

Lets say i have a nodeapi module taht wannts to add a second stage (part 2 of a multipart form) to the original node form ONCE ITS BEEN SUBMITTED. How would your example be modified to do that?

Could you provide a skeleton?

thanks much for the good articles



I am getting following

I am getting following error
Call to undefined function _multistep_example_format_values(). What may be the reason.



I presume you haven't

I presume you haven't included the function that was defined in this example.



with pager...

I think the problem with combining this code and a pager_query is the test for $form_values:
if ($form_values === NULL)

When you click one of the links provided by the pager, no $form_values are passed and the form does not display any results. A quick workaround: change the above line to something like
if ($form_values !== NULL OR $_GET['page'])

That will allow results to be displayed either if the $form_values array is not empty (i.e. the form was just submitted), or if the $_GET array has a value in the 'page' element (i.e. you are trying to look at a paged result list).

Use at your own risk... this is probably not really the correct way to do this, but in some situations might be an OK workaround.



Could you possibly provide

Could you possibly provide an example?? I have trying for a week to implement pager in this with no luck....




I get errors too, but it's Ok, the idea is clear :). A usefull peace of code, really.



Your suggestions are very

Your suggestions are very concrete and helpful. I’ll pass them on to writers who are maintaining their own blogs. Keep up the good work, its appreciated by the little guys..



this just doesn't work

Copy pasted this in to a module I'm developing in Drupal 5.1 and I don't get to step 2. No values are passed to the form after the first submit?

Would dearly love to know how to get this goign as I've lost a day on it.



I'm seeing this in 5.2 too

I'm seeing similar behavior; sometimes you have to submit twice before the value actually makes it into the '$form_values' array.


Ken Colwell

Check for Caching

I had this same problem. Try using the cache exclude module to exclude the url of your form and this problem will go away.



Same here

I'm having the exact same problem right now.

When submitting my form, my form function gets called twice and I need to submit my form twice before my new values are taken into account.



I am using this for a complex search form but just one problem

This is a really useful article. I am trying to create my own complex search form that is displayed as a tab under the search page. This solution works really well except that I am displaying a sortable table. When I click on a sortable column on my table it redisplays the original form only. Can anyone offer suggestions on how to redisplay the sortable table?


Adam Young

Can this work for the 'get'

Can this work for the 'get' form method? I tried it by simply adding:

$form['method'] = 'get';

...but now there are no values in $form_values. Reply

Adam Young

Using the 'get' method

Are we able to use the 'get' method with this technique? When I add this to the form:

$form['#method'] = 'get';

... the $form_values are empty. Reply


Can't wait to try it. I've

Can't wait to try it. I've been searching for anything like this for countless hours. This is exactly what I wanted to do.



Finally! I've been searching

Finally! I've been searching all over trying to find out how to do this. Should have know better and came to the lullabots first!





Cool, this is very helpful. I made a slight modification and didn't check if $form_values === NULL up top, and instead checked if $form_values != NULL, and if it is not null, I built the $form['results'] array, so that the form shows, with the user's value, along with the results. Perfect.




Everything works great, apart from one thing: How can i add a pager to the displayed table? Please help, I really need this feature. Is pagination possible in this???



Upgraded to 5.16 data sent to e-mail not displaying


I had an earlier version of Drupal and edited my article.module so as to display different fields for various areas on my site. All was working well until I upgraded to 5.16. Now the forms still display fine and e-mail the data but the formatting and field data are not in the submitted e-mail to me.

Before I got e-mailed:
Name: Joe Blow
Address: 90210

Now I get:

(persons name) has sent a message at (page name with form)

What could the problem be?

Please talk to me like I am six years old... I have racked my limited brain over this and it is fried.




How do you check for errors

Since the code only checks if values were submitted how do you check for errors during validation before running a query for your results? For example if it was a search form, and you don't want to run the search query unless the form passes validation. Actually in most cases you'd like to know if it passed validation before displaying any kind of result.



The only table tutorial worth reading.

I don't think I have found one tutorial that just plainly, simply, explained how the hell to add table output in your form function.

It seems every article out there just has the code snippet, but not what function it is supposed to go in and that was the issue.

A nice combination is your tutorial and's tutorial:

But again, I could not have gotten kpbowlers to function without your to the point tutorial.

well done and thanks!





How use this for blocks?