I am a pretty seasoned web developer but am new to Drupal module development. I have read a ton of stuff on designing forms, my forms display fine but the validate / submit never seems to happen and I THINK I have my module coded correctly. I have reduced to a super simple module that duplicates my issue and I know I am just missing something super simple but I would really appreciate somebody pointing me in the right direction - I am sure somebody with more experience can tell me in two seconds what I am doing wrong. My module appears as follows

<?php
/* $Id$ */

function test_menu() {
  $items = array();

  $items[] = array(
    'path' => 'test',
    'title' => t('Test Module'),
    'callback' => 'test_page',
    'access' => user_access('access test content'),
    'type' => MENU_CALLBACK
  );

  return $items;
}

function test_perm() {
  return array('access test content');
} // function train_perm()

function test_page() { 
  global $testLog;
  $testLog = "<br>---log---<br>";

  $output = '';
  $output = drupal_get_form('test_form');
  $output .= $testLog;
  return $output;
}

function test_form() { 
  global $testLog;
  $testLog .= "Building form<br>";
  $form = array();
  $form['formvalue'] = array(
    '#type' => 'textfield',
    '#title' => t('Text field'),
    '#default_value' => "");
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'));

  return $form;
}  

function test_form_validate($form_id, $form_values) {
  global $testLog;
  $testLog .= "Validating form<br>";
}

function test_form_submit($form_id, $form_values) {
  global $testLog;
  $testLog .= "Submitting form<br>";
}

So the form displays fine and I fill in a value and hit submit. I expect the "log" messages below will show that it is validating the form and then submitting the form but when it comes back the textfield is once again blank and it never called validate or submit. What am I doing wrong? I keep reading and re-reading the form stuff and it SEEMS I have everything in place. I am so confused.

Comments

pwolanin’s picture

The data (log) you want to see is going away because you are trying to display it on a different page view than the form submission. The forms API does a redirect after form submission is complete, so all the $_POST values, global variables, etc are cleared.

To do a log the way you want, you need to stuff this message into the session. Or, better yet, use drupal_set_message() which already does this for you. Or try setting $form['#redirect'] = FALSE.

See this post for how to output the results of the form below the form: http://drupal.org/node/136726

see also: http://api.drupal.org/api/5/function/drupal_redirect_form

---
Work: BioRAFT

kdorff’s picture

Setting

   $form['#redirect'] = FALSE

did indeed solve my problem. I saved the values from the submit into the session and used those values when generating my output which seems to work great. Doesn't seem to be the most direct method, but, I can fine tune things now that I am better understanding how things are working.

kdorff’s picture

Also, general comments for how I am doing this are welcome. My module will be to display a single page such as

   dropdown
   dropdown
   submit

   many rows of filtered day (filtered based on the dropdowns above, always present even before submit)

So, when you first come to the page the filtered rows of data (from the database) will be displayed based on the default values for the two dropdowns. When you change the dropdowns and submit the rows of data will change according to the selected values. Really simple.

Currently, I just have to go to

   http://site.com/test

and display it. I have made a "primary link" that goes to "/test" to display as I haven't yet figured out how to just make the link part of the main navigation. I think I can figure this out, but, my primary goal right now is getting the submit to work correctly.

I ordered the new Drupal book "Pro Drupal Development" by by John VanDyk and Matt Westgate which reportedly shipped today (a few days early) from Amazon so I should have it on Wednesday.

Thanks,
Kevin

dwees’s picture

Here's probably what happened. You were working on creating the link from your menu and it didn't work a few times, and then finally you got it working but it still doesn't show up in your menu.

This is probably because the menus are cached in the database to save time for future executions, so you can clear the cache of your database, or put your menu code outside of the if ($may_cache) conditional statement.

This will put your menu item as part of the regular navigation menu. Once you have the menu item working the way you want it to, as long as it's not a dynamic path or anything funky like that, place it inside the conditional (making sure to clear your Menu CACHE in your database first).

Edit: Actually there's a tiny error in your menu code. Use the following.


function test_menu($may_cache) {
  $items = array();

  if ($may_cache) {

  }

  $items[] = array(
    'path' => 'test',
    'title' => t('Test Module'),
    'callback' => 'test_page',
    'access' => user_access('access test content'),
    'type' => MENU_NORMAL_ITEM // MENU_CALLBACK's don't appear in the menu
  );

  return $items;
}

Dave

pwolanin’s picture

The code above is not quite right- a menu item should only be returned when $may_cahce == TRUE, or == FALSE. It is a bug to return it under both conditions.

function test_menu($may_cache) {
  $items = array();

  if ($may_cache) {

    $items[] = array(
      'path' => 'test',
      'title' => t('Test Module'),
      'callback' => 'test_page',
      'access' => user_access('access test content'),
      'type' => MENU_NORMAL_ITEM // MENU_CALLBACK's don't appear in the menu
    );
  }

  return $items;
}

---
Work: BioRAFT

dwees’s picture

Well fair enough that's true.

However when you are testing your code maybe something like:

function test_menu($may_cache) {
  $items = array();

  if (!$may_cache) {

    $items[] = array(
      'path' => 'test',
      'title' => t('Test Module'),
      'callback' => 'test_page',
      'access' => user_access('access test content'),
      'type' => MENU_NORMAL_ITEM // MENU_CALLBACK's don't appear in the menu
    );
  }

  return $items;
}

is more appropriate?