This tutorial, for beginning and intermediate Drupal programmers, includes basic and some advanced features of the Form API (example: multistep forms). Intermediate programmers may want to skip down to code sample #8. The tutorial includes the ability to copy and paste the following code snippets into a module for viewing and experimenting.

First, learn how to get the code snippets working. For an existing Drupal 6 site:

  1. Create a new directory in sites/all/modules and name it 'my_module'
  2. Create a file named my_module.info in the my_module directory with the following contents:
  3. name = My module
    description = Module for form api tutorial
    core = 6.x
    
  4. Create a file and name it 'my_module.module'. Cut and paste the first code sample into the my_module.module file (note that it's preferable to omit the closing ?> tag)
  5. Enable the "My module" module on the administer/site building/modules page.
  6. Type the following in the browser address bar: http://yoursite_site_url/?q=my_module/form or http://yoursite_site_url/my_module/form depending on your configuration.
  7. For each code sample in the tutorial, completely replace the code in my_module.module with the new code snippet and type the following in the browser address bar: http://yoursite_site_url/?q=my_module/form or http://yoursite_site_url/my_module/form depending on your configuration.

Note: Throughout the sample code are explanation comments.
This code uses drupal “hooks”, from the drupal API.

Comments

cquezel’s picture

Comments on the tutorial

If you are a newbie to Drupal, (like me) you probably want to know the following things about this tutorial:
There is a discussion on why the closing “?>” may be omitted here: http://ca.php.net/basic-syntax.instruction-separation

On example 1

The 'name' key has no special meaning and any value may be used. This key value is used to generate ids and names in the generated html.
'textfield' is just the Drupal way of saying a html text input.
Drupal caches some information on modules menus. For example, if you want to change my_module_menu to give a new title to the form, you will have to disable and enable your module before refreshing to see this change.
Wrapping Titles and descriptions in t() is not required as of v6: http://drupal.org/node/140311
More info on menu here: http://drupal.org/node/102338
More info on form API here: http://api.drupal.org/api/file/developer/topics/forms_api.html/6
Where is the 'description' value used?

On example 6

Note that the validation, as expressed, allows an empty value for the 'year_of_birth' field.
The example introduces the 'value' key for $form_state other keys are documented here: http://drupal.org/node/144132
Drupal has functions to help form designers and date_validate is one out of the bunch: http://api.drupal.org/api/group/form_api/6
It would probably be a good thing to express the error message in terms of the field title (i.e. $form['year_of_birth']['#title']).
The '#validate' property may be used to explicitly register form validation handlers to forms and buttons: http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...
The '#element_validate' may be used to explicitly register element validation handlers to any element: http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...
The difference between '#validate' and '#element_validate' is described here: http://drupal.org/node/169815

On example 7

The '#submit' property may be used to explicitly register form submit handler to forms and buttons: http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...

On example 9

The example introduces the 'storage' key for $form_state see: http://drupal.org/node/144132
I’m not so sure it is a good design decision to move the field validations in the form validation in this case.

VinceW’s picture

A few readers had some problems finding the correct url to the new form.

if you enter this snippet of code on top of the module, you will get a new menu entry, from where you can reach the form. (I adapted the code on: http://drupal.org/node/206761 a bit to fit this tutorial. Search on that page for: Add the page to hook_menu).

<?php
function my_module_menu() {
  $items = array();
  $items['my_module/form'] = array(
    'title' => t('My form'),
    'page callback' => 'my_module_form',
    'access arguments' => array('access content'),
    'description' => t('My form'),
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}
?>

After reloading/refreshing the admin -> modules the menu-item will show up.

Hope it's useful for someone
VinceW

-=[ Your Information Matters ]=-

-=[ Your Information Matters ]=-

eglon’s picture

Thank you, this is a really good tutorial. Keep up the good work:)

Christian

CJOKRAYNER’s picture

I found this more by mistake.

Create a menu item in admin/build/menu with the path set to "my_module/form" (Leaving out the quotation marks)

Job Done.

Pip Pip

dazmcg’s picture

hi! great tutorial, but I'm having an problem which I think is related to the fact that I'm calling the form using the node/add method? If this is so, can it be explained?

I get this error when I use the drupal_get_form() method:
warning: array_merge_recursive() [function.array-merge-recursive]: Argument #2 is not an array in /home/web/active/drupal-6.10/modules/node/node.pages.inc on line 134.

My module can be viewed here:
http://home.imprison.me.uk/t/test1.module.txt

Any tips?

Cheers!

dazmcg’s picture

If I want to take this tutorial and add on additional functionality so that the form and its elements maps to a CCK type with fields like 'first name', 'last name' and 'year of birth', which when submitted, will create a new node of the cck type, injecting the values from the form into the new node?

Building on this, if I have CCK field types which have particular widgets attached (eg: tags, which have the autocomplete functionality), how would I expose this in my form?

Thanks!

Neil_in_Chicago’s picture

There's a lot more to CCK than meets the eye.
I've been working with some CCK fields, and a couple
var_dump($form);
var_dump($form_state);
show more complexity than I was expecting!

Here's the best documentation I've been able to find (note how little of it is drupal.org!):
CCK 2 Documentation | groups.drupal.org
What is the Content Construction Kit? A View from the Database. | Lullabot
CCK Documentation Resources | CCK API
API reference | CCK API
Database abstraction layer | CCK API
Unraveling the mysteries of the cck (and the cck docs) | The Empowerment
Updating CCK Modules from 5.x to 6.x | drupal.org

seanr’s picture

Here's a workaround in a multistep node form:

/**
 * Implementation of hook_form_alter().
 *
 * When first adding the node, put the 'Title' field on its own page in a
 * multistep node form.  We need to do this in hook_form_alter() itself
 * instead of a form_id-specific form alter so that we're likely to come after
 * everyone else's alterings, e.g. taxonomy, menu, etc.
 */
function example_form_alter(&$form, $form_state, $form_id) {
  $type = node_get_types('type', $node);
  if ($form_id == 'example_node_form') {
    if (arg(1) != 'add') {
      $node = $form['#node'];
    }
    
    if (isset($node->section)) {
      $section = $node->section;
    }
    elseif (isset($form_state['section'])) {
      $section = $form_state['section'];
    }
    elseif (isset($form_state['values']['section'])) {
      $section = $form_state['values']['section'];
    }
    
    if (empty($section)) {
      [step 1 fields here]
    }
    else {
      [step 2 fields here]
      
      // Add a submit handler to copy the version values from
      // $form_state['storage'] to $form_state['values']
      $form['#submit'][] = 'crmapi_node_form_submit';
      // For the actual submit button, add a handler to clear out
      // $form_state['storage'] entirely so that we actually submit the form.
      $form['buttons']['submit']['#submit'][] = 'crmapi_node_form_final_submit';
      
      if (arg(1) == 'add') {
        // Fix FUBAR Drupal handling of chewckboxes in multistep forms
        _example_form_checkboxes($form);
      }
    }
  }
}


/*
 * Helper function to step through form elements and fix default
 * values for checkboxes.
 */
function _example_form_checkboxes(&$form) {
  foreach (element_children($form) as $child) {
    if ($form[$child]['#type'] == 'checkbox') {
      if ($form[$child]['#default_value'] == TRUE) {
        $form[$child]['#attributes'] = array('checked' => 'checked');
      }
    }
    elseif ($form[$child]['#type'] == 'fieldset') {
      foreach (element_children($form[$child]) as $grandchild) {
        if ($form[$child][$grandchild]['#type'] == 'checkbox') {
          if ($form[$child][$grandchild]['#default_value'] == TRUE) {
            $form[$child][$grandchild]['#attributes'] = array('checked' => 'checked');
          }
        }
      }
    }
  }
}

It's really not recursive, but it works well enough for the standard node forms (I don;t think I've seen too many node forms with nested fieldsets)

advseb’s picture

The documentation of hook_menu (http://api.drupal.org/api/function/hook_menu/6) says that the title and description property must be untranslated. So you should remove the t() function in your example.

owenmc’s picture

Is the expression $form_state['clicked_button'][#id] == 'edit-next' correct? Should it actually be: $form_state['clicked_button'][#id] == 'next' or $form_state['clicked_button'][#value] == 'Next >>' ? I'm confused.

jkiwanuka’s picture

I have a form based on the above tutorial. I've managed to get it working with all the code. But when I try to submit the data to a database, it only inserts the data from the second page.

the code snippet I have is:


// Handle page 1 submissions
  if ($form_state['clicked_button']['#id'] == 'edit-next') {
    $form_state['storage']['page_two'] = TRUE; // We set this to determine
                                               // which elements to display
                                               // when the page reloads.
                                              
    // We save our values below in the $form_state['storage'] array so they
    // will carry forward to subsequent pages in the form.
    $form_state['storage']['page_one_values'] = $form_state['values'];
  }
  // Handle page 2 submissions
  else {
    /*
     Normally, some code would go here to alter the database with the data
     collected from the form. Here we just set a message with drupal_set_message()
     so you know the code is working.
     */
	 
	 
    //drupal_set_message('Your form has been submitted');
    
db_query("INSERT INTO {test} (first, last, dob, name, mail, password) VALUES ('%s','%s',%d,'%s', '%s', '%s' )", 
$form_state['values']['first'], //page 1
$form_state['values']['last'], //page 1
$form_state['values']['year_of_birth'], // page 1
$form_state['values']['name'],  //page 2
$form_state['values']['mail'],  //page 2
$form_state['values']['pass']); // page 2
drupal_set_message(t('Your form has been saved.'));

	
	
	unset ($form_state['storage']); // This value must be unset or we will
                                    // not be redirected! This is because
                                    // $form_state['rebuild'] gets set to TRUE
                                    // when 'storage' is set. See code sample
                                    // #9 for more on this.
                                   
    $form_state['redirect'] = 'node'; // Here's how we redirect the user.
  }
}

What do i do to make sure the first page field values are submitted and passed to the database as well.

jkiwanuka’s picture

As soon as i asked the question I solved it! I had to state the page one values using

$form_state['storage']['page_one_values'] = $form_state['values'];

so the database query becomes


db_query("INSERT INTO {test} (first, last, dob, name, mail, password) VALUES ('%s','%s',%d,'%s', '%s', '%s' )", 
$form_state['storage']['page_one_values']['first'], //page 1
$form_state['storage']['page_one_values']['last'], //page 1
$form_state['storage']['page_one_values']['year_of_birth'], // page 1
$form_state['values']['name'],  //page 2
$form_state['values']['mail'],  //page 2
$form_state['values']['pass']); // page 2
drupal_set_message(t('Your form has been saved.'));

And it worked. Seems a long way around though.

amira’s picture

sorry for interubtion...
iam alittle bit new in drupal world ..the tutorial and ur comment is more than helpful and make me understand alot how i can create a form and deals woth apis of drupal.

i have a question : what about if i want to select all data from the test table..?
i tried by replacing ur sql statement by:

db_query("select * from {test}");

sure no change :D...i guess that is because i have to fetch the rows that return and return in the form ?? but i tried but no change too :(

if any ideas i'll be greatfull

thanks in advance

amira’s picture

sorry for interubtion...
iam alittle bit new in drupal world ..the tutorial and ur comment is more than helpful and make me understand alot how i can create a form and deals woth apis of drupal.

i have a question : what about if i want to select all data from the test table..?
i tried by replacing ur sql statement by:

db_query("select * from {test}");

sure no change :D...i guess that is because i have to fetch the rows that return and return in the form ?? but i tried but no change too :(

if any ideas i'll be greatfull

thanks in advance

ampdude’s picture

This is great! I've been scouring the entire web looking for a solution like this. What I would like to do is replace the standard registration form with this solution. I have a very long registration page I need to break down into steps. Logically, I would expect to be able to create all my custom fields in the standard registration form via User Management\Profiles (so they're added to the database) and then build a substitute form in this module. Linking to this from the 'create new account,' the user profile should be viewable and editable like normal, right?
If so, I can follow the example jkiwanuka has provided above, but I'm weak with the mySQL. I do not understand the VALUES portion of the script.

thanks!

jflesher’s picture

$tempSetting = theme_get_setting('theme_setting_name');
$tempSetting = variable_get('theme_setting_name');
$tempSetting = theme('get_setting', 'theme_setting_name')
This will return a NULL if called in a module but not if called from the theme:

To answer my own question:
$settings = theme_get_setting('theme_name');
$tempSetting = settings['theme_setting_name'];

gjansen’s picture

Hello,

I want to change the path to this form.

For example:
http://yoursite_site_url/my_module/form
New path:
http://yoursite_site_url/contact/my_module/form

1) Is this possible?
2) If yes, how can I do it?

ccdechesney’s picture

It all depends on how you define the menu item or items and what other menu items there are already defined. For your example let's assume that if you type http://yoursite_site_url/contact in your browser you get the contact page or something else that makes sense.

This will produce a normal menu (probably in Navigation) that will be labeled MyModule and will go to a page and call function mymodule_overview:

function mymodule_menus(&$items) {  //don't forget the ampersand or it won't work
  $items['mymodule'] = array(
    'title' => 'MyModule',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_overview',
    'type' => MENU_NORMAL_ITEM,
  );
}

You can also attach a couple of menu tabs to the MyModule page by adding this inside the above function:

  $items['mymodule/list'] = array(
    'title' => 'List',
    'access arguments' => array('access content'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['mymodule/add'] = array(
    'title' => 'Add',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_add',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  ); 

There have to be at least two tabs before any will show up. In the above example, the List tab does the same thing as the normal menu item MyModule, and then the Add tab goes to a page for adding whatever and calls the function mymodule_add. The page for adding is also available at http://yoursite_site_url/mymodule/add.

If you just want to add a form tab to the contact page, then the path would be http://yoursite_site_url/contact/form and the code to create that menu (path) is:

 $items['contact/form'] = array(
    'title' => 'Form',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_form',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  ); 

If on the other hand you want a tab on the contact page that says MyModule and then several tabs on the MyModule page and one of them should be form, then:

 $items['mymodule'] = array(
    'title' => 'MyModule',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_overview',
    'type' => MENU_NORMAL_ITEM,
  );
$items['contact/mymodule'] = array(
    'title' => 'List',
    'access arguments' => array('access content'),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => 0,
  );
  $items['mymodule/form'] = array(
    'title' => 'Form',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_form',
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  ); 

You can attach menu tabs to all sorts of existing pages this way. 'user/1/list' would show up on the profile page of User 1, for example. Play with it and see what you can do. One last note: there can only be one MENU_DEFAULT_LOCAL_TASK per page.

urlstwohim3’s picture

I have tried and tried but cannot get the My module to show up in modules.
Anyone else having the same problem?

jdevelop’s picture

How can this tutorial be modified for drupal 7

leopardhe’s picture

I followed all the steps here
But when I typed in

"http://yourhost/my_module/form" or
"http://yourhost/?q=my_module/form"

Just nothing happened. I didn't get a page with the form on it. I

just couldn't figure out why. Anyone can help?

Thanks

ccdechesney’s picture

Here's a sequence that has helped me in troubleshooting:
1.Can I enable my module? If not, there is something wrong with my module.
2. Is my menu showing up? If not, the problem is with the code creating the menu item. Check spelling etc. until it works.
3. In the menu callback routine, add "Hello world!" to $output and return $output instead of creating the form. When I choose the menu item, do I see "hello, world"? If not, check spelling and code details. Once that is working, then
4. Put in the actual call to drupal_get_form in place of "hello world", make a simple form, maybe just a Submit button in the form function. Don't forget to return $form. Try it again until this much works.
5. Create a submit function and by changing it make sure you can either rebuild the form or finish and go elsewhere. Play with just a few fields until it does what you want.

Now you can add more fields of different sorts and work toward your actual functionality.

Slurms MacKenzie’s picture

Here is my version of the final step's code for Drupal 7. A couple things to point out: I used the drupal_build_form instead of drupal_get_form because the latter resets the form_state array.

I also used the #value attribute with an isset() instead of #default_value because the latter only works the first time you load the form, otherwise the default settings of Drupal forms keeps values that the user inputs which causes headaches.

Lastly, I used the form_state['input'] index instead of ['values'] because the 'input' index is essentially the post array values from this is form and that behavior was what I am used to when programming php forms. I just couldn't get the 'values' index to do what it needed to do. Anyway, feel free to make suggestions because I am still very much learning this as I go.

<?php
function my_module_menu() {
  $items = array();
  $items['my_module/form'] = array(
    'title' => t('My form'),
    'page callback' => 'my_module_form',
  	'access callback' => true,
    'description' => t('My form'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}


// Main function that calls the drupals form building function and passes
// a the name of this modules custom form building function 
// 
//@return $form - array built by drupal_build_form
//
function my_module_form(){
	
	$form_state = &$form_state;
	if($form_state == null){
		$form_state = form_state_defaults();
	}
	return drupal_build_form('my_module_my_form', $form_state);
}


//
// This is the main form building function for this module 
// 
// @param array $form 
// @param array reference $form_state
// @return array $form
function my_module_my_form($form, &$form_state) {

  // Display page 2 if $form_state['storage']['page_two'] is set
  if (isset($form_state['storage']['page_two'])) {
    return my_module_my_form_page_two();
  }
  
  $form['name'] = array(
    '#type' => 'fieldset',
    '#title' => t('Name'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );
   
// Change/add the #default_value for the first name, last name, and
// birth year to show their old values so when the "Add another name"
// button is clicked, they will retain their values.
  $form['name']['first'] = array(
    '#type' => 'textfield',
    '#title' => t('First name'),
    '#value' => (isset($form_state['input']['first'])) ? $form_state['input']['first'] : "", 
    '#description' => "Please enter your first name.",
    '#size' => 20,
    '#maxlength' => 20,
  	//'#required' => true,
  );
  $form['name']['last'] = array(
    '#type' => 'textfield',
    '#title' => t('Last name'),
  	'#description' => 'Please enter your last name',
    '#value' => (isset($form_state['input']['last'])) ? $form_state['input']['last'] : "", 
   	//'#required' => true,
  );
  $form['year_of_birth'] = array(
    '#type' => 'textfield',
    '#title' => "Year of birth",
    '#description' => 'Format is "YYYY"',
    '#value' => (isset($form_state['input']['year_of_birth'])) ? $form_state['input']['year_of_birth'] : "", 
  
  );
 
  // Add new elements to the form
  if (isset($form_state['storage']['new_name'])) { // This value is set after
                                                   // "Add new name" button
                                                   // is clicked.
      $form['name2'] = array(
        '#type' => 'fieldset',
        '#title' => t('Name #2'),
        '#collapsible' => TRUE,
        '#collapsed' => FALSE,
      );
      $form['name2']['first2'] = array(
        '#type' => 'textfield',
        '#title' => t('First name'),
        '#description' => "Please enter your first name.",
        '#size' => 20,
        '#maxlength' => 20,
        '#value' => (isset($form_state['input']['first2'])) ? $form_state['input']['first2'] : "", 
      );
      $form['name2']['last2'] = array(
        '#type' => 'textfield',
        '#title' => t('Last name'),
        '#value' => (isset($form_state['input']['last2'])) ? $form_state['input']['last2'] : "", 
      );
      $form['year_of_birth2'] = array(
        '#type' => 'textfield',
        '#title' => "Year of birth",
        '#description' => 'Format is "YYYY"',
        '#value' => (isset($form_state['input']['year_of_birth2'])) ? $form_state['input']['year_of_birth2'] : "", 
      );
    }
  $form['clear'] = array(
    '#type' => 'submit',
	'#value' => 'clear form',
	'#validate' => array('my_module_my_form_clear'),
  );
 
  // Adds "Add another name" button, if it hasn't already been clicked.
  if (empty($form_state['storage']['new_name'])) {  // This value is set after "Add new name" button is clicked.
      $form['new_name'] = array(
        '#type' => 'submit',
        '#value' => 'Add another name',
        '#validate' => array('my_module_form_new_name'),
      );
    }
 
  $form['next'] = array(
    '#type' => 'submit',
    '#value' => 'Next >>',
  );
  return $form;
}

//Creating a new element, 'new_name' in the $form_state['storage'] array
// sets the value used to determine whether to show the new
// fields on the form and hide the "Add another name" button.
function my_module_form_new_name($form, &$form_state) {
    $form_state['storage']['new_name'] = TRUE;
    
    $form_state['rebuild'] = TRUE; // Calling this explicitly will cause the
                                   // default submit function to be skipped
                                   // and the form to be rebuilt.
}


// Unsets the form_state input values and rebuilds the form so
// that it is blank
// @param array $form 
// @param array reference $form_state
function my_module_my_form_clear($form, &$form_state) {
	$form_state['storage']['new_name'] = null;
	if(isset($form_state['input']) && is_array($form_state['input'])){
		unset($form_state['input']);
    }  
    $form_state['rebuild'] = TRUE; // Calling this explicitly will cause the
                                   // default submit function to be skipped
                                   // and the form to be rebuilt.
}

// Returns the form variable for the second page with a color field and the
// final submit button for the complete form  
function my_module_my_form_page_two() {
  $form['color'] = array(
    '#type' => 'textfield',
    '#title' => 'Favorite color',
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );
  
  return $form;
}


// Validates the form. Checks if first name and last name are set, if year of birth is
// between 1900 and 2000. If the "new name" button is set, it performs the same validation
// on those. API form_set_error function is used when one of these rules isn't satisfied
// 
// @param array $form
// @param array reference $form_state
function my_module_my_form_validate($form, &$form_state) {
	  if (isset($form_state['storage']['page_two'])) {
	    $color = $form_state['input']['color'];
	    if (!$color) {
	      form_set_error('color', 'Please enter a color.');
	    }
	    return;
	  }
	
    $year_of_birth = $form_state['input']['year_of_birth'];
    $first_name = $form_state['input']['first'];
    $last_name = $form_state['input']['last'];
    if (!$first_name) {
        form_set_error('first', 'Please enter your first name.');
    }
    if (!$last_name) {
        form_set_error('last', 'Please enter your last name.');
    }
    if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
        form_set_error('year_of_birth', 'Enter a year between 1900 and 2000.');
    }
    if (isset($form_state['storage']['new_name']) && $form_state['storage']['new_name']) {
        $year_of_birth = $form_state['input']['year_of_birth2'];
        $first_name = $form_state['input']['first2'];
        $last_name = $form_state['input']['last2'];
        if (!$first_name) {
            form_set_error('first2', 'Please enter your first name.');
        }
        if (!$last_name) {
            form_set_error('last2', 'Please enter your last name.');
        }
        if ($year_of_birth && ($year_of_birth < 1900 || $year_of_birth > 2000)) {
            form_set_error('year_of_birth2', 'Enter a year between 1900 and 2000.');
        }
    }
}

function my_module_my_form_submit($form, &$form_state) {
  // Handle page 1 submissions	
  if ($form_state['clicked_button']['#id'] == 'edit-next') {
    $form_state['storage']['page_two'] = TRUE; 
                                               
    $form_state['storage']['values'] = $form_state['values'];
    $form_state['rebuild'] = true;     
  }
  else{
   // Normally, some code would go here to alter the database with the data
   //  collected from the form. Sets a message with drupal_set_message()
   //  to validate working code.
   // 
    drupal_set_message('Your form has been submitted');
    unset ($form_state['storage']);
    $form_state['rebuild'] = true;                                
    $form_state['redirect'] = 'node'; // Redirects the user.
  	
  }

}
?>
sidrasultana’s picture

multistep form works great for me. bundles of thanks

derekwhiteside’s picture

Hello, I am new to the form API and would like to test/experiment.

My question is, why is a new module necessary to use the form API?
Is it possible to use the form API on a php-enabled "page" content node without creating a module?

I ask because our drupal install is "locked down" and I don't have sufficient privileges to add a module.

Thanks in advance,

dw

dabellator’s picture

Hey everyone. I'm new to building modules and I've been working it from several angles but keep returning to the same problem. I've created the my_module.info file, copied the basic form code into a my_module.module file, and can see the option to enable my_module in my module page. Trouble is, once I enable my_module, the returned page is blank. Any page on my site I try to access is similarly blank.

Sorry if this question is redundant, I couldn't find any other help out there, but I'm sure I'm just missing it. Anyone have a fix for me?

Thanks!
-JB

Ajay Gadhavana’s picture

Its really cool tutorial, you can do most of things related to form.
awesome man.
keep posting