When I write my own module by using drupal_get_form to customize my form, I got a blank output. And furthermore, the example in here, http://api.drupal.org/api/HEAD/file/developer/topics/forms_api.html, didn't work for me neither. Do you know anything wrong with it? There is my code, I hope it would be something help.

function todo_perm() {
    return array('create todo items', 'manage own todo items');
}

function todo_node_info() {
    return array('todo' => array('name' => t('to-do'), 'module' => 'todo'));
}

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

    $items[] = array(
        'path' => 'todo',
        'title' => t('To-do List'),
        'callback' => '_todo_form',
        'access' => user_access('access content'),
        'type' => MENU_CALLBACK);

    return $items;
}

function _todo_form() {

    // summary / title
    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => t('Email'),
        '#required' => TRUE,
        '#default_value' => $node->email,
        '#weight' => -5,
        '#description' => t('Email Address')
        );

    $output = drupal_get_form('_todo_form', $form);
    print theme("page", "ahah");
    return $output;
}

function todo_validate($form_id, $form_values) {
    form_set_error('', t('You must enter a valid email address.'));
}

Comments

AjK’s picture

You tagged your post with Drupal 5.x but your sample use of drupal_get_form() is 4.7 so you might start there ;)

Just simplistic samples to get you started (note how 5.x "pulls" the form whereas 4.7 "pushes" the form).

4.7


    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => t('Email'),
        '#required' => TRUE,
        '#default_value' => $node->email,
        '#weight' => -5,
        '#description' => t('Email Address')
        );

    $output = drupal_get_form('_todo_form', $form);
    return theme("page", "ahah") . $output;

5.x


    $output = drupal_get_form('_todo_form');
    return theme("page", "ahah") . $output;


function _todo_form() {

    // summary / title
    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => t('Email'),
        '#required' => TRUE,
        '#default_value' => $node->email,
        '#weight' => -5,
        '#description' => t('Email Address')
        );

    $output = drupal_get_form('_todo_form', $form);
    return $output;
}
pwolanin’s picture

The code above for 5.x is wrong- the code needs to look like:


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

  if ($may_cache) {
    $items[] = array(
        'path' => 'todo',
        'title' => t('To-do List'),
        'callback' => 'drupal_get_form',
        'callback arguments' => array('_todo_form'),
        'access' => user_access('access content'),
        'type' => MENU_CALLBACK);
  }
    return $items;
}

function _todo_form() {

    // summary / title
    $form['email'] = array(
        '#type' => 'textfield',
        '#title' => t('Email'),
        '#required' => TRUE,
        '#default_value' => $node->email,
        '#weight' => -5,
        '#description' => t('Email Address')
        );
 
   $form['submit'] = array('#type' => 'submit', '#value' => t('Submit') ); 

    return $form;
}

Note that the output of the page is now drupal_get_form('_todo_form')

In 5.x, the form_id is (by default) the same as the name of the builder function, so if you are going to use _todo_form() as the name of the builder function, then you need to implement the validate and submit functions as _todo_form_validate() and _todo_form_submit()

---
Work: BioRAFT

weekendli’s picture

I actually try the your solution first, however, the problem for me about that is I can't get other form hooks triggered, e.g. hook_validate. Here is a summarize of my code, the problem for this is that the _validate, _submit wouldn't be trigger, even the form was corrected rendered.

appointment.module

function appointment_perm() { ... }

function appointment_menu($may_cache) {
    $items = array();
    $items[] = array(
	'path' => 'appointment',
	'title' => t('Book An Appointment'),
	'callback' => 'drupal_get_form',
	'callback arguments' => '_appointment_form',
	'access' => user_access('access content'),
 	'type' => MENU_CALLBACK);

    return $items;
}


function _appointment_form() {
    $form['email'] = array(
	'#type' => 'textfield',
	'#title' => t('Email'),
	'#size' => 30,
	'#maxlength' => 64);
  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));

  return $form;
}

function appointment_validate($form_id, $form_values) {
  form_set_error('', t('You must enter a valid email address.'));
}

function appointment_submit($form_id, $form_values) {
    drupal_set_message(t('Your form has been saved.'));
}
pwolanin’s picture

You need to use "_appointment_form" as the base for the other function names (note underscore at the start):


function _appointment_form_validate($form_id, $form_values) {
  form_set_error('', t('You must enter a valid email address.'));
}

function _appointment_form_submit($form_id, $form_values) {
    drupal_set_message(t('Your form has been saved.'));
}

---
Work: BioRAFT

weekendli’s picture

That's exactly what I'm looking for!!!!

Somebody should really mark this out in the examples. Those form hooks are different from the regular hooks. Thanks!!!!!

AjK’s picture

Erm, it's not entirely wrong, it's just not complete. The idea was to show that in 5.x drupal_get_form() uses the pull method. If I were to write a "complete solutions" what would be the fun in that?

sleepingmonk’s picture

I've tried this stuff as well as the example in the Forms API Quickstart Guide. No matter what I do the best outcome I've had is the word 'Array' being printed on the page. What am I missing to render the whole form? Here's the example I'm playing with:



<?php
function test_form() {
  // Access log settings:
  $options = array('1' => t('Enabled'), '0' => t('Disabled'));
  $form['access'] = array(
    '#type' => 'fieldset',
    '#title' => t('Access log settings'),
    '#tree' => TRUE,
  );
  $form['access']['log'] = array(
    '#type' => 'radios',
    '#title' => t('Log'),
    '#default_value' =>  variable_get('log', 0),
    '#options' => $options,
    '#description' => t('The log.'),
  );
  $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
  $form['access']['timer'] = array(
    '#type' => 'select',
    '#title' => t('Discard logs older than'),
    '#default_value' => variable_get('timer', 259200),
    '#options' => $period,
    '#description' => t('The timer.'),
  );
  // Description
  $form['details'] = array(
    '#type' => 'fieldset',
    '#title' => t('Details'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['details']['description'] = array(
    '#type' => 'textarea',
    '#title' => t('Describe it'),
    '#default_value' =>  variable_get('description', ''),
    '#cols' => 60,
    '#rows' => 5,
    '#description' => t('Log description.'),
  );
  $form['details']['admin'] = array(
    '#type' => 'checkbox',
    '#title' => t('Only admin can view'),
    '#default_value' => variable_get('admin', 0),
  );
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#size' => 30,
    '#maxlength' => 64,
    '#description' => t('Enter the name for this group of settings'),
  );
  $form['hidden'] = array('#type' => 'value', '#value' => 'is_it_here');
  $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
  return $form;
}

function test_page() {
  return drupal_get_form('test_form');
}
?>

Thanks for any help. I've been messing with this for hours!

--
To Your Success!

pwolanin’s picture

Are you doing this in a module, or just in a page with PHP format?

Try a simpler form (a single element) first.

---
Work: BioRAFT

sleepingmonk’s picture

UPDATE!!
I actually solved this one too I think. I had an epiphany while reading over this post. I remembered that there is such a thing as hook_link and realized that I must have been trying to invoke that hook by naming my function application_link. I've changed it's name and I think it's working properly now.

I'm still only halfway through this project though and I'm sure I'll trip on something else. Thanks for the support!

Drupal and the Drupal Community ROCK! Hopefully I get to a level where I can contribute back as well.

-------------------

Actually I figured out why the form wasn't rendering. I'm trying to build a module and I had an error in the menu callback that I found by accident. I've fixed that and things seem to be working so far. My next roadblock is to figure out how to have one module display different forms based on the url.

i.e.

I'm having trouble with functions for this. I assumed I could just add two new functions one for the form and the other for the drupal_get_form and add an item to the menu. It seems though, that things crash when I return a second drupal_get_form, even though the page is only calling one function at a time.

Actually, I've had both forms working with menu links and everything but when I logout I get a white screen of death and an error message.

Fatal error: Cannot use string offset as an array in .../drupal-5.1/includes/theme.inc on line 552

I've built things one function at a time and the error only occurs when I add the return of the second drupal_get_form.

Any help on this would be appreciated.

Here's the code structure:

<?php
/* $Id$ */

function application_perm() {
  return array('access link');
}

function application_menu($may_cache) {
  $items = array();
  $items[] = array('path' => 'apply_now',
    'title' => t('Online Application'),
    'callback' => 'application_page',
    'access' => user_access('access content'),
    'type' => MENU_NORMAL_ITEM,
  );
  $items[] = array('path' => 'apply_now',
    'title' => t('Online Application Link'),
    'callback' => 'application_link',
    'access' => user_access('access content'),
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

function application_page() {
  return drupal_get_form('application_form');
}

function application_link() {
  return drupal_get_form('application_link_form');
}

function application_link_form(){
	  $form = array (
    '#id' => 'application_link',
    '#prefix' => '',
    '#suffix' => '',
    '#method' => 'POST',
    '#action' => 'apply_link',
    '#value' => '',
  );

  ...various form elements...

return $form;
}
	

function application_form(){

  $form = array (
    '#id' => 'application',
    '#prefix' => '',
    '#suffix' => '',
    '#method' => 'POST',
    '#action' => 'apply_now',
    '#value' => '',
  );
  ...various form elements...

  return $form;
}

--
To Your Success!