I just finished implementing a little php interface to a mysql db, easy enough to do...took an hour or so. My question is what is the benefit to using the drupal forms API over writing your own php forms? I coded this myself, and it was quick enough. Saved me from having to learn a new interface, so I think it was actually faster. Thoughts?

Comments

ardas’s picture

sorry, but what is php forms ?

----------------
Regards,
Dmitry Kresin, ARDAS group - Web site development, Drupal services, Software development, IT outsourcing.

nevets’s picture

Some things I see as an advantage of using the Drupal API forms (in no particular order); Once you learn it, you can roll out forms quickly, it provides the logic for validation and redisplaying to form if errors, it provides a clean way for seperating out both validation and submition from form generation, it provides extensions beyond standard forms (autocomplete for example) and allows others to provide extenstions, it seperates defining the form from the generation of the html and makes it straightforward to theme the output different if you choose, it allows others to extend/add elements to existing forms. In short, it provides a nice tool kit for building forms.

But all that aside if you want to make a module that defines a content type based on a node (which has advantages of its own) you need to know the forms API. If you want to define a module with a custom block that has configuration options you need to know the forms API. And if you want to define a module that uses the standard settings interface you need to know the forms API.

crashpoint’s picture

hi nevets,

I wanted your help as I read your post regarding the plus points of using forms api. I had done the following

created an html form with a textfield username and a submit button.

My requirement was that upon submission these passed params should be displayed on a page. But how do i go about doing that.

Initially I wrote a simple php code which just displays the elements that it gets from the GET array and upon creation this page was given node no node/14

I put in action for the form I created as node/14. But as obvious as it was when user enters name and clicks on submit these params are passed to a static page. During that time I hunted the drupal site for a form api and came across the api described at http://drupal.org/node/37775 and also went through the quick start guide. But as in the quick start guide they gave code for form creation as

$form['foo'] = array(
  '#type' => 'textfield',
  '#title' => t('bar'),
  '#default_value' => $edit['foo'],
  '#size' => 60,
  '#maxlength' => 64,
  '#description' => t('baz'),
);

Where does this code go? in create content -> page. I did not understand this part.

I'd greatly appreciate any help form your side

nevets’s picture

Here is a small sample, make a file in modules/myform called myform.module and paste the following code into it.
Enable the module to see it in action

<?php

/**
 * A small example module of using the form api
 * to display and process a form
 * that is not used to extend the basic node content type
 *
 * In this sample the form collects two numbers
 * and multiplies them together
 */


/**
 * Implementation of hook_help().
 *
 * Throughout Drupal, hook_help() is used to display help text at the top of
 * pages. Some other parts of Drupal pages get explanatory text from these hooks
 * as well. We use it here to provide a description of the module on the
 * module administration page.
 */
function myform_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      // This description is shown in the listing at admin/modules.
      return t('The myform module multiplies two numbers together.');
  }
}

/**
 * Implementation of hook_perm().
 *
 */
function myform_perm() {
  return array('mutiple numbers');
}

/**
 * Implementation of hook_menu().
 *
 */
function myform_menu($may_cache) {
  $items = array();

	$access = user_access('mutiple numbers');
	
  if ($may_cache) {
  	// This determines the path used to show the form and also makes a menu entry
  	// This first path is for the entry form
    $items[] = array('path' => 'myform/sample', 'title' => t('sample form'),
      'callback' => myform_sampleform, 'access' => $access);
      
    // This path is for the routine that actually does the multplication
    // It is only setup as a callback (no menu entry)
    $items[] = array('path' => 'myform/multiple', 'title' => t('Multiplication Results'),
      'type' => MENU_CALLBACK, 'callback' => myform_multiple, 'access' => $access);
	}
	
	return $items;
}

function myform_sampleform() {
	$form = array();
	
	// Build up the form
	// See api.drupal.org/api/4.7/file/developer/topics/forms_api.html (quickstart guide)
	// and api.drupal.org/api/4.7/file/developer/topics/forms_api_reference.html (forms api)
	// for more information on creating forms
	
	$form['value1'] = array(
	  '#type' => 'textfield',
	  '#title' => t('Value 1'),
	  '#size' => 4,
	  '#maxlength' => 4,
	  '#description' => t('The first value to perform the multiplication with.')
	);
	
	$form['value2'] = array(
	  '#type' => 'textfield',
	  '#title' => t('Value 2'),
	  '#size' => 4,
	  '#maxlength' => 4,
	  '#description' => t('The second value to perform the multiplication with.')
	);
	
	// Make sure we have a submit button

	$form['submit'] = array('#type' => 'submit', '#value' => t('Multiple values'));

	
	// drupal_get_form produces the form
	// which return to the drupal system
	// which produces the page
	
	// The first parameter to drupal_get_form
	// is the form id.  It also determines the
	// default validation and submit function names
	//
	// In this case
	//	Validation: myform_sample_validate()
	//  Submit: my_form_submit()
	
	return drupal_get_form('myform_sample', $form);
}

function myform_sample_validate($form_id, $form_values) {
	if ( !isset($form_values['value1']) ) {
		form_set_error('value1', t('You must provide the first multiplication value.'));
	}
	else if ( !is_numeric($form_values['value1']) ) {
		form_set_error('value1', t('The first multiplication value must be a number.'));
	}	

	if ( !isset($form_values['value2']) ) {
		form_set_error('value2', t('You must provide the second multiplication value.'));
	}
	else if ( !is_numeric($form_values['value2']) ) {
		form_set_error('value2', t('The second multiplication value must be a number.'));
	}	
}

function myform_sample_submit($form_id, $form_values) {
	// Submit routines do not directly produce any output
	// They do something with the form values
	// which is typically to store them in the database
	// then return a path to determine what page is shown next
	
	// In this case the path constructe includes the two values
	
	return 'myform/multiple/' . $form_values['value1'] . '/' . $form_values['value2'];
}
	

function myform_multiple($value1, $value2) {
	$output = '<p>';
	$output .= $value1. ' * ' . $value2 . ' = ' . ($value1 * $value2);
	$output .= '</p>';
	
	return $output;
}
?>
drupalGuy181’s picture

Nevets:

I'd like to thank you very much for providing an example! This is 100 times more helpful than posting all the API functions. Drupal really should have added something like this to the "Forms API Quickstart Guide".

Vidarls’s picture

If I remember correctly it can be found at http://api.drupal.org

-Olegu
http://www.zbz5.net/

patrickharris’s picture

Very helpful example.

CdnStrangequark’s picture

Yeah, again, this example was wayyy better than anything on the api reference site or in the handbooks. The API reference site should include something like this under its examples.

shoq’s picture

We would like to reorganize and simplify the editing form for both Page and Story module.

But this Form API and the form tree seem so complicated, and so fragmented across multiple hooks, that it's just impossible for a non-drupal guru to get a handle on any of it without a huge amount of study and a level of documentation that doesn't seem to exist yet.

Can someone please give me a clue about how to approach this problem:

Presently, the "Tags" textbox is displayed in a with the reading "categories". We want to add a second tags field just like it (for particular kinds of tags) , and then wrap both fieldsets in a larger container Div (or other fieldset) which can converted to tab container with client side javascript (bypassing the existing collapser.js). Thus, both fieldsets will be converted to Tabs within the tabs container. This part is easy, IF I can maniulate the form source with classes and HTML elements that make sense to my tabs code.

The Form_Alter hook lets me act on the form tree via a formID, but I don't understand how to reorganize chunks of the form tree here, or whether I even can do that at all.

(It doesn't seem this is what form_alter is really for, being geared more to minor tweaks than to big structural changes to the tree).

The only real discussion I have find of manipulating the tree at all is this linl, and it is so dense and writtren for experts, that no mere mortals can make heads or tails of it. Further, other users report the code example doesn't work at all.

http://drupal.org/node/48643

Is there any example anywhere of someone redesigning the way the user's settings and data entry forms can be organized? If we could see one example of how things were hooked and configured for say, the Page module, it shouldn't be too hard to extrapolate from there.

Just one example...please.. just one? Drupal's node editing is hardly compact, or even very intuitive. We cannot believe we are the first to want to spruce it up a bit, nor can we believe it's quite as hard as it seems to be.

nevets’s picture

Basically what you want to do is move the form element from the existing form to a spot "lower" in the tree. In the example that follows for the page module edit form, we wrap the taxonomy fieldset in our own fieldset (not very pratical, but hopeful it will help you progress).
Word of warning, your module must either be alphabitically after the module whos fields you want to modify or have a greater weight.
To try it out make a directory called zformmodifier under the modules directory and place the example below in a file called zformmodifier.module.

<?php

function zformmodifier_form_alter($form_id, &$form) {
	// drupal_set_message("Form ID: $form_id");

	if ( $form_id == 'page_node_form' ) {
		// Useful if you want to explore the form fields
		// drupal_set_message("<code>" . print_r($form, TRUE) . '

');

// Get the part of the form we want to wrap
$taxonomy = $form['taxonomy'];

// Remove it from the form
unset($form['taxonomy']);

// Add the wrapper, here we just use a fieldset

$form['taxonomywrapper'] = array('#type' => 'fieldset',
'#title' => 'My taxonomy wrapper',
'#weight' => $taxonomy['#weight']);

// Now add the original form part back as a child of the wrapper
$form['taxonomywrapper']['taxonomy'] = $taxonomy;

}
}

dman’s picture

Yes, if you know how to do forms in HTML with PHP already, and you want a normal enter-submit form where you catch all your content yourself, the API does seem to just get in the way

But once you want to work with validation, persistance and themes, it starts paying off.

And when (like this query) you want to modify an existing Drupal form, it's gold.
(But still a bit painful)

My methods are -

  1. Create a lightweight development module.
  2. Impliment hook_form_alter()
    function demo_form_alter($form_id,&$form){
      drupal_set_message("Altering '$form_id' &quot;.htmlspecialchars(print_r($form,1)).&quot;");
    }
    
    function demo_install() {
      // ensure this always runs AFTER core.modules have done their forms;
      db_query("UPDATE {system} SET weight = 3 WHERE name = 'demo'");
    }
    
  3. That little bastard will run all over your site, showing what's going on, Find the page you want, and study the structure you want to manipulate. Yeah it's huge.
  4. Significantly, your new module may get called asynchronously with the other modules that act on the form. If you want to mess with functionality that something else has but there (adding categories is a form_alter action done to node-form by taxonomy.module) You have to be called after it's done its thing. Do this by setting the system weight of your new module.
    That's what the demo_install does. I listed it above because you have to have it there from the very start of testing or it gets hairy.
  5. So, right. The categories fieldset is put into the form as $form['taxonomy'][1] and [2] (I've enabled two vocabs, as I think that's what you want to do)
  6. It basic, although not trivial to manipulate that fieldset using normal array assignment.
  7. Adding your own field additions (like the majority of modules do) is easier, and you don't have to worry (much) about load order.
    function demo_form_alter($form_id,&$form){
      drupal_set_message("Altering '$form_id' &quot;.htmlspecialchars(print_r($form,1)).&quot;");
      if($form['#id'] == 'node-form'){
        $form['taxonomy']['whocares'] = array(
          '#type' => 'checkbox',
          '#title' => 'Do I care?',
        );
      }
    }
    

I believe your desire for 'tabs' (A major restructuring, I think) could begin to be addressed by trying to go :

function demo_form_alter($form_id,&$form){
  // Shift ALL the current form into two bags.
  if($form['#id'] == 'node-form'){
    $tab1 = array(
      '#type' => 'fieldset',
      '#title' => 'Node'
    );
    $tab2 = array(
      '#type' => 'fieldset',
      '#title' => 'Tags'
    );
    // move categories into new placeholder
    $tab2['taxonomy'] = $form['taxonomy'];
    unset($form['taxonomy']);

    // move everything else into the other tab (but not the form properties)
    foreach(element_children($form) as $id){
      $tab1[$id] = $form[$id];
      unset($form[$id]);
    }
    $form['tab1'] = $tab1;
    $form['tab2'] = $tab2;
  }
} 

... works for me, take it from there!

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

shoq’s picture

Nevets, Dman..

Thank you both for the extensive replies. I will now delve into your solution and let you know how I progressed.

I think dman is reading my frustration about this whole API business well. I consider myself a developer, but not a programmer with a deep skillset. Someone like me has little trouble with most CMS systems using templates, or some other view system, but drupal just jams my mental circuits completely. Even so, I suspect I have many more skills than most users who just want to add some degree of customization to the standard content admin forms--and have more time to try and wrestle with it.

Perhaps some of those confused users can add a comment here, and suggest just how significant the problem is--and for how many. I suspect this is one of those very large issues that just doesn't get mentioned enough because people fear they are just missing something and will look stupid asking for help.

The Drupal community boasts about how powerful and flexible the system is, but if making basic changes to the way users interface a node's attributes and permissions is this complex, it's hard to really sustain that boast to any but the most skilled or persistent developers with a lot of time to invest.

Perhaps there is some middle ground wizard helper that could provide a more traditional templating mechanism that treats the form/tree elements as simple template variables of some sort? That way, the designer (me, could just layout the named elements in a visual way, and let drupal and the engineers worry about the innards.

We're really pretty happy with what we've been able to do thus far. Drupal made some of the expected difficult tasks easy. It's the things we assumed would be easy that are proving very hard.

Oh well, back to it. Thanks again for the detailed help.

dman’s picture

What you are asking is beyond almost every templating system out there.
Take a working, inline portion of a dynamically rendered, themed part of core UI, place it elsewhere in the page and still work. Yo'd have to do it with string parsing!

And remember that themes kick in all over the place, so you should never be coding ANY HTML.

At no time could there be a 'template' listing, say :

{body_fields}
{taxonomy_fields}
{path_fields}
{publish_fields}

for you to mess with, as
- what shows up when is programatic,
- the ordering of the fields is programatic,
- and it's 'altered' by other modules inserting their own blocks at any time.

Instead, we have

array(
  'body' => array(...)
  'taxonomy' => array(...)
  'path' => array(...)
  'publish' => array(...)
);

... which isn't that different conceptually.
You have direct access to the variable values at all times.
You can change the order or nesting as needed today.
You can even set the titles or descriptions of fields from other modules.

Prior to forms API, custom modules only had access to the concatenated STRING version of the rendered form parts.

Note also, at the far end of this process, it would have been possible to get similar results just through theming - you impliment your own theme_form() and render just the form elements you want, in the order you want. That's where you go if you are keener to work with HTML than code.
It depends on if you see this enhancement a structural or visual change. I gave you the semantic solution. The layout-driven solution comes from the other end.

function demo_theme_form($element) {
  if($element['#id'] == 'node-form'){

  $action = $element['#action'] ? 'action="' . check_url($element['#action']) . '" ' : '';
  $taxonomy_block = theme($element['taxonomy']);
  unset($element['taxonomy']);

  foreach(element_children($element) as $id){
    $tab1 .= theme('form',$element[$id]);
  }

  return "
    <form '$action' method='${element['#method']}' 'id='${element['#id']}' "
    . drupal_attributes($element['#attributes']) ." >
      <div id='div1'>" . $tab1 . "</div>
      <div id='div2'>". $taxonomy_block ."</div>
    </form>
  ";
  } else {
    return theme_form($element);
  }
}

... that's pseudo-template code (Meaning it probably won't work as-is), and possibly contains a gotcha or two, but it does the same thing at RENDER time rather than code time.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

heine’s picture

I'd recommend to theme specific forms by their form_id or callback: theme_form_id or theme_callback.
--
The Manual | Troubleshooting FAQ | Tips for posting | Make Backups! | Consider creating a Test site.

dman’s picture

I knew I was overlooking/forgetting one big step :-B Makes more sense, I felt something was a bit screwy with the implimentation, but I knew the theory I was aiming at.
Just an untested brain-fart.

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

eaton’s picture

in traditional HTML layout, a form is dirt simple. There's nothing -- technically, at least -- that prevents you from sticking HTML form data right in your node's body. You can point the form to a url on your drupal site, and write a module that takes the incoming $_POST[] data and processes it.

FormAPI exists not because making HTML forms is so hard, but because a robust API is needed to define forms in a modular fashion so that other plugin modules and other themes can rearrange, dynamically alter, make additions to, and override the default behavior of any other forms in the system.

As a result, changing the layout and behaviour of core drupal forms may require some code, but it can be done without changing *any of the core files* in the drupal system. That makes upgrading and security easier, and also helps you keep better track of the changes you're making versus what was there already.

You might look at the webform.module if all you want to do is make a simple form that takes data and emails it, or something like that. It, too, uses FormAPI as its backend -- it just presents a friendly front-end for those who don't need the complexities.

--
Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

darkpollo’s picture

You can point the form to a url on your drupal site, and write a module that takes the incoming $_POST[] data and processes it.

Im not sure about that. I have made a simple block with a php self form and it works only to Admin and non registered users. No way to make it work with registered users.

I dont want to learn an API, i only want to use my old php code on drupal...

Any help?

I have asked this on the forum with no luck here:
http://drupal.org/node/186782

Thank you very much

ardas’s picture

Eaton is right.
FAPI helps to hide complexity and provide nice features for site developers. For instance, there is no resizable textarea in HTML (you need to write javascript for that). FAPI gives you a simple way to specify resizable => TRUE and that's all. You can develop your own complex form elements and easily use them on your form such as tabs from jstools.module.

I can compare Drupal FAPI form development with something like Visual C++ IDE where you can just choose a desired element and drop it onto the form and then fill its attributes :)

----------------
Regards,
Dmitry Kresin, ARDAS group - Web site development, Drupal services, Software development, IT outsourcing.

Zoologico’s picture

Could you comment on what function to call from a node template?

From your example, I would want to do this:

<?php print myform_sampleform(); ?>

However, when I add this to my node template, I get an "internal server error".
:(

Am I even on the right track?

nevets’s picture

but for the example you need to create the module myform (the example goes in a file called myform.module in the directory modules/myform). Note if you are using Drupal 5 you will also need a myform.info file (see below). Copy the sample and place in myform.module, then enable the module. Now you can use the path 'myform/sample' to access the form. If you site is at http://www.example.com the URL would be http://www.example.com/myform/sample (without clean URLS that would be http://www.example.com/index.php?q=myform/sample).

If using Drupal 5 you will also need a myform.info (also in modules/myform) that looks something like this

name = My Form
description = Playpen for form API
Zoologico’s picture

Thanks for the response.
I see how you got to your explanation.
Primarily, I see this:

    $items[] = array('path' => 'myform/sample', 'title' => t('sample form'),
      'callback' => myform_sampleform, 'access' => $access);

This is where you declare from where the form will be accessible.

I am using the contemplate module. I have a content type of item (custom one). Beyond this I am using the contemplate module to make the custom node type appear the way I want to in terms of layout. Nothing fancy really, just an HTML template that has all the right variables in the locations I want them to show up in the HTML template's layout.

What I am looking to do is make this form be part of this template. I am not using your exact form example, but I made two hidden elements and kept the submit button. I also am using your validate and submit functions.

So in my module I have the form building, the validate function, and the submit function.

In fact, here is my module code:

<?php

/**
* Function used to declare and build the buy form
*/
function form_buyitem(){

	//Declaring array
	$form = array();
	
	//Using global user variable
	global $user;
	
	//Building the form
	
	//Capturing current user
	$form['form_user'] = array(
      '#type' => 'hidden',
      '#value' => t($user->uid)
    );
	
	//Capturing current node
	$form['form_node'] = array(
      '#type' => 'hidden',
      '#value' => t($node->nid)
    );
	
	//Capturing current user
	$form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('BUY')
    );
	// drupal_get_form produces the form
    // which return to the drupal system
    // which produces the page
   
    // The first parameter to drupal_get_form
    // is the form id.  It also determines the
    // default validation and submit function names
    //
    // In this case
    //    Validation: myform_sample_validate()
    //  Submit: my_form_submit()
   
    return drupal_get_form('form_buyitem', $form);
} // function form_buyitem()

/**
* Function used validate the buy form (form_buyitem)
*/
function form_buyitem_validate($form_id, $form_values) {
    if ( !isset($form_values['form_user']) ) {
        form_set_error('form_user', t('You must must be logged in to buy an item.'));
    }
    if ( !isset($form_values['form_node']) ) {
        form_set_error('form_node', t('You can only buy when viewing an item.'));
    }
} // function form_buyitem_validate($form_id, $form_values)

/**
* Function used to submit;  this is the form that performs the action on the form's values;
* it then returns the URL of the page that it shown once the 
*/
function form_buyitem_submit($form_id, $form_values) {
    // Submit routines do not directly produce any output
    // They do something with the form values
    // which is typically to store them in the database
    // then return a path to determine what page is shown next
   
    // In this case the path constructe includes the two values
   
    return 'node';
} // function form_buyitem_submit($form_id, $form_values)

?>

My question is what am I missing from the proper usage and how would I go about having this form be part of every custom node content?

nevets’s picture

If I understand you are trying to add a "buy" button to certain content types. There are at least a couple of ways you could approach this, the easy one would be to the link hook to add a "buy" link to the approriate content types, you can also also only add the link for people who are logged in or might make it "login to buy" for people who are not logged in.

You could also use the nodeapi hook to add the form to during the 'view' op when viewing the selected content. Note you can once again choose to show/not show the button based on if someone is logged in or not (or vary the text of the button)

Side notes, no real need to add $user->uid or $node->nid. $user->uid will be the same when view the form and on validate (using global $user) and if the form is for a node, $form_values already has the nid. It is also better to use '#type' => 'value' (than hidden) as it truely hides the values (the user can not even see them if they look at the html).

Zoologico’s picture

That's exactly what I am trying to do.
I think I follow your points, let me see:

I am using the nodeapi's view operation to enact other things in my node. I can drop all of that code into my view operation.
Then, I also change all instances of '#type' => 'hidden' to '#type' => 'value'.

This is also brought up in the API QuickStart Guide:

"If a form has a submit function, then hidden form values are not needed."

I'm still not clear on this point you made:

"Side notes, no real need to add $user->uid or $node->nid. $user->uid will be the same when view the form and on validate (using global $user) and if the form is for a node, $form_values already has the nid."

Finally, if I put all this code into my nodeapi's view operation (already did this), what code do I insert into my HTML template so the button this form has within it gets displayed?
I think once I understand these two things I will be in really good shape.

Zoologico’s picture

What code would you use to make this work in the nodeapi hook under the view op?

Could you fill this in as an example?

<?php
function item_manager_nodeapi(&$node, $op) {
		
		//Choose actions based on the operation being perfomed
		switch ($op) {
						
			//The node content is being assembled before rendering. The module may add elements $node->content prior to rendering. This hook will be called after hook_view().
			//The format of $node->content is the same as used by Forms API.
			case 'view': {
				
			         //What goes here?
				
			}
?>

What code would I use in my node template to get it to display in a particular table cell?

Could you fill this in as an example?


<table>
<tr>
      <td>What goes here to get the button made above to appear?</td>
</tr>
</table>
dman’s picture

//The format of $node->content is the same as used by Forms API.
case 'view': {
  $node->content['item_manager'] = array(
    '#value' => 'your addition to the node',
    '#weight' => 1
  );
}

Positive weight should put your addition below the normal body, negative above it

... I imagine. Never actually tried it myself

.dan.
How to troubleshoot Drupal | http://www.coders.co.nz/

dantina’s picture

Hi Nevets, When I tried to use the example, I got the following error:

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'myform_sample' was given in ...\includes\form.inc on line 218.

Any idea what I am doing wrong?

guillaumeduveau’s picture

Same here, Drupal upgrades must have broken this...?

igable’s picture

here's my error:
warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'myform_sample' was given in /var/www/drupal-5.3/includes/form.inc on line 217.

pbland’s picture

I was having the same problem, when I looked in the API and realized in 5.2 there's only 1 argument in drupal_get_form(); I also looked in the handbook at this tutorial (http://drupal.org/node/82936) and instead, now do return system_settings_form($form); at the end of your myform_sampleform().

hth,
Paul

---------------------------------------------------------------
My drupal site: Vacation-Places

_michel_’s picture

Hi

I am trying to follow your example to learn about form API.
I get the following error :

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'myform_sample' was given in /home/dr5/www/includes/form.inc on line 218.

Did I do something wrong?

Regards.

Michel.

web2’s picture

Hi,
I want to display Create content poll form in block.
I found your link while i am trying to produce form for Create content poll and I think you can help me.
I write form codes manually but I stuck with data validation error for form_token. I write php code for it which i found in forum and same error again . The codes are here :-

<form action="/?q=node/add/poll"  method="post" id="node-form" enctype="multipart/form-data">
<div>
<div class="node-form">
  <div class="standard">

<input class="autocomplete" type="hidden" id="edit-taxonomy-tags-1-autocomplete" value="http://tveed.com/?q=taxonomy/autocomplete/1" disabled="disabled" />

<div class="form-item">

  <input type="text" maxlength="128" name="title" id="edit-title"  size="60" value="" class="form-text required" />
</div>

<div class="form-item">
 <label for="edit-taxonomy-tags-1">Category of TV Shows: <span class="form-required" title="This field is required.">*</span></label>
 <input type="text" maxlength="255" name="taxonomy[tags][1]" id="edit-taxonomy-tags-1"  size="60" value="" class="form-text form-autocomplete required" /> 
<div class="description">A comma-separated list of terms describing this content. Example: funny, bungee jumping, "Company, Inc.".</div>
</div>

<input type="hidden" name="changed" id="edit-changed" value=""  />
<input type="hidden" name="choices" id="edit-choices" value="2"  />


<div class="form-item">
 <input type="hidden" maxlength="128" name="choice[0][chtext]" id="edit-choice-0-chtext"  size="60" value="Yes" class="form-text" />
</div>
<div class="form-item">
 <input type="hidden" maxlength="128" name="choice[1][chtext]" id="edit-choice-1-chtext"  size="60" value="No" class="form-text" />
</div>

<input type="hidden" name="edit[form_token]" id="a-unique-id" value="<?php print drupal_get_token('poll-form'); ?>" />


<input type="hidden" name="form_id" id="poll-node-form" value="poll_node_form"  />
  </div>


<input type="submit" name="op" id="edit-submit" value="Submit"  class="form-submit" />
</div>

</div></form>
        

I also try to call drupal form function in block but fail :-

<?php

$output = drupal_get_form('advpoll_form');
print $output;

?>

I still struggle for success. Please help me.

Visit me at http://nashikit.com

heine’s picture

print drupal_get_token('poll-form');

You need to use the right value, which would be (from the top of my head): poll_node_form. However, I'm sure this approach is doomed.

As to II: how does it fail? Do you use the core poll module or another module?

Node forms can be printed elsewhere with:

$node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
return drupal_get_form($type .'_node_form', $node);

PS It's best to open a new thread for these kind of questions.
--
The Manual | Troubleshooting FAQ | Tips for posting | How to report a security issue.

web2’s picture

Hi,

I change in codes as per your suggestion

<?php
print drupal_get_token('poll-form');
?>

but still I get the warning message "Validation error, please try again. If this error persists, please contact the site administrator."
Any idea?

The URL of the site :- http://tveed.com/?q=frontpage

Thanks again for your helping hand.

Visit me at http://nashikit.com

web2’s picture

Hi,
Thanks Heine,

I get success with the codes

$node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
return drupal_get_form($type .'_node_form', $node);

Visit me at http://nashikit.com

ardas’s picture

To embed an existing form into another form or any other place try to use www.drupal.org/project/subform_element
This module allows you to build a form which consists of one subform element which embeds any of existing forms.
----------------
Regards,
Dmitry Kresin, ARDAS group - Web site development, Drupal services, Software development, IT outsourcing.

codrakon’s picture

hi did u solve your problem?

i am trying to create this form and retrieve the values of the checkboxes to be processed in drupal. perhaps you can help me get started. the rest of my post is here http://drupal.org/node/777464

hi All

I am trying to get the values from a form a created in drupal 6.x. i have not used this type of code to create the form

<?php
$form['cta_miniform_name'] = array(
				'#type' => 'textfield',
				'#size' => 20,
				'#maxlength' => 40,
				'#default_value' => t('Name'),
				'#required' => TRUE,
		);
?>

because it is too cumbersome to create the form i wanted. instead i have used code like this

<?php
function cta_admin($name = NULL) {
    
    drupal_add_js($base_path . 'sites/all/modules/cta/formscript.js');
    drupal_add_css(drupal_get_path('module', 'cta') .'/cta_style.css');
    
    $x = 0;
    $y = 0;
    
    $outputtable = '<form id="cta-blueflag"><div id="tableresult" style="width:400px;"><table><tr><td>Name</td><td>Details</td><td>Address</td><td>Skill Area</td><tr>';
    
    $result = db_query('SELECT * FROM {kcfblocks_blueflag} WHERE contacted = 0');
    
    while ($data = db_fetch_object($result)){
	$x = $data->memberid;
	$y++;
	$outputtable .= '<tr>
	<td><input type="checkbox" value="' . $x . '" id="contacted' . $y . '">' . $data->name . '</td>
	<td>' . $data->email . '<br/>' . $data->company . '<br/>' . $data->telephone . '<br/>' . $data->contacttype . '</td>
	<td><a onclick="showhide(\'addresstable\',' . $x . ')">' . substr($data->address1, 0, 5) . '...</a>
	<table class="addresstable" style="display: none;" id="addresstable'. $x . '">
	<tr><td>' . $data->address1 . '</td></tr>
	<tr><td>' . $data->address2 . '</td></tr>
	<tr><td>' . $data->town . '</td></tr>
	<tr><td>' . $data->district . '</td></tr>
	<tr><td>' . $data->postcode . '</td></tr>
	<tr><td>' . $data->country . '</td></tr></table>
	<td><a onclick="showhide(\'skillstable\',' . $x . ')">' . substr($data->skillarea, 0, 5) . '...</a>
	<table class="skillstable" style="display: none;" id="skillstable'. $x . '">
	<tr><td>' . $data->skillarea . '</td></tr>
	<tr><td>Skill Description<br/>' . $data->skilldescription . '</td></tr></table>';
	$outputtable .= '</tr>';
    }
    
    $outputtable .= '</table></div><br/></form>';
    
   
  
    
  $output = '<div id="ctaadmin">CTA Admin<br/><h3>Recent Blue Flag Membership applications</h3>' . $outputtable . '</div>' . drupal_get_form('cta_adminform');
  return $output;
}

function cta_adminform(){
    $form['submit'] = array(
				'#type' => 'submit',
				'#value' => t('Submit'),
		);
		
    return $form;
}

function cta_adminform_submit(){
    
    drupal_process_form('cta-blueflag', $form, $form_state);
    
    dsm($form);
    
}
?>

as u can see im trying to get the values out of my custom HTML form but i am unable to do so...

please could somebody help me...

thanks

chris

dman’s picture

Well, that was a mistake then.
Don't do it that way.
Either use the Form API, or do your own form handling, but you can't make it up as you go along and get the advantage of built-in Form validation and processing at the same time.

Only after you've totally understood Form API successfully would you know what rules to break and override as you are trying to do here.

For now, just build your forms by hand - if Form API isn't making sense to you yet.

dropcube’s picture

Remember that Form API, is an API. Once you know how to work with it, you will see how you save your time. A lot of functionality is yet implemented and you don't need to worry about that, form validation, form submition handler, form custom theming, and many other.

If you take one day to learn how to use it, you will save a lot of time and bugs.

Ronny

anner’s picture

Ok, I see your points, and will learn it if I need to make or edit a module. But if I have one or two simple forms, a day may be more of an investment than my employer would appreciate. Another point: would form API code be portable? If I was forced by my employer to move everything out of drupal (either into another cms or into static content) the form API stuff would all have to be recoded in pure php/html, right? Since they (the ptb) haven't signed off on drupal officially yet, I think I'll hold off on the form API stuff for now.

nevets’s picture

If you are going to place html/php forms in a node and the form has any side effects (place something in a database, email, etc) I would strongly recommend using the excerpt module and hand setting the excerpt/teaser. Otherwise you can find the code running twice (once for teaser, once for full view with unwanted results).

anner’s picture

I already use this. Thanks

dropcube’s picture

Ok, if that is the point, I agree with you, but if ou are developing Drupal Modules I strongly recommend that you take a time to learn how good is it.

tmj2k7’s picture

I have to say that drupal's form api makes module development so much quicker. It does take getting used to, but it is a functional api. In fact, the whole module API system is like a godsend from the direct coding I had to do to get mambo modules working.

www.thelinuxuser.com

casperl’s picture

OK, so I have decided to go the API route and though struggling along, I am making progress.

The API is an impressive work, feature rich and capable. Well done! I will never know whether the hours and hours I invested in the API would not have been better served (and more profitable) through building more websites rather than coding and learning the API. But now I have wonderful, capable, state-of-the-art websites.

I have another problem with the API though. And that is that from one Drupal version to the next Drupal upgrade the API changes. And sometimes the API undergoes considerable changes. That means that I have to go from one already written and running website to the next exsiting website and modify themes, modules and custom code in order to upgrade. I hate fiddling with things that already works and has been running for a while! Sometimes progress sux! And the more custom code that uses the API, the bigger this workload becomes. It feels like two steps forward and one step backwards every time an upgrade comes along!

And (see the 4.7.4 upgrade) sometimes code tweaking is necessary not even with major upgrades but with security fixes as well.

As Drupal sites grow, in terms of size, features and complexity, I can visualise a substantial liability in adapting existing code in future! It is a bit like having the Y2K-coding crisis every six months!

I doubt that it is workable for a code-compatibility upgrade path to exist in Drupal where I did not have to tweak code that already works, but it would have been nice...

Casper Labuschagne
Where am I on the Drupal map on Frapper?

ardas’s picture

Honestly speaking, Drupal Form API is one of the greatest features in Drupal which makes it to be much better than any other CMS :)
----------------
Regards,
Dmitry Kresin, ARDAS group - Web site development, Drupal services, Software development, IT outsourcing.

sharique’s picture

Subscribing
--
Sharique uddin Ahmed Farooqui
Web Developer
http://it.Managefolio.com

Sharique Ahmed Farooqui

summit’s picture

Subscribing
I also have a First argument is expected to be a valid callback, '_node_form' was given in form.inc on line 217 but nodecomment module with cck , greetings, Martijn

juinz’s picture

Hi, im trying to put the example to work, but i get the same error:

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'myform_sample' was given in /home/dr5/www/includes/form.inc on line 218.

With all the corrections, im lost now and dont know what to do. Can someone update the example with all features inclused? Im working on drupal 5.x.

If anyone can also help me in this:

My module is based on print an output, like:

<div id="mymodule_autosuggest_div">
<input type="textfield" value="" />
</div>

And i need an autocomplete feature for my input (from a custom table). im trying to make the example work, to later use the autocomplete feature like:

http://drupal.org/node/42552

How to make my input work with autocomplete? I need serious and newby-oriented help with forms, and the documentation is a lil complex for me... where to find newby-oriented help, with examples and all? :'(

txs

pd] hopefully, i need help newbie-oriented for drupal... :'(

stevemasters@cherryhill.co.uk’s picture

OK, finally got a version of nevets Small Form Sample to work in Drupal 6.x.

Create myform.info, myform.mofule and save to /sites/all/modules/myform
Go to /admin/build/modules, enable 'Small Form Sample' and Save configuation
Go to /admin/user/permissions, enable 'myForm module' and Save permissions
Go to /myform/sample and test.

I'm a bit of a Drupal newbie and I'm not sure if everything I changed was needed but it works for me.

Can anyone can see a problem or a better way?

; $Id$
name = Small Form Sample
description = The myform module multiplies two numbers together
core = 6.x

/**
* Version: Drupal 6.x
*
* A small example module of using the form api
* to display and process a form
* that is not used to extend the basic node content type
*
* In this sample the form collects two numbers
* and multiplies them together
*/


/**
* Implementation of hook_help().
*
* Throughout Drupal, hook_help() is used to display help text at the top of
* pages. Some other parts of Drupal pages get explanatory text from these hooks
* as well. We use it here to provide a description of the module on the
* module administration page.
*/
function myform_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      // This description is shown in the listing at admin/modules.
      return t('The myform module multiplies two numbers together.');
  }
}

/**
* Implementation of hook_perm().
*
*/
function myform_perm() {
  return array('mutiple numbers');
}

/**
* Implementation of hook_menu().
*
*/
function myform_menu() {
  $items = array();

  // This determines the path used to show the form and also makes a menu entry
  // This first path is for the entry form
  $items['myform/sample'] = array(
	'title' => t('sample form'),
  	'page callback' => 'drupal_get_form',			// drupal_get_form, registers the given form in drupal
   	'page arguments' => array('myform_sample'),		// myform_sample, the name of the form to register
	'access arguments' => array('mutiple numbers'),
  );
      
  // This path is for the routine that actually does the multplication
  // It is only setup as a callback (no menu entry)
  $items['myform/multiple'] = array(
	'title' => t('Multiplication Results'),
  	'page callback' => 'myform_multiple',			// myform_multiple just returns page text 
   	'page arguments' => array(2, 3),
	'access arguments' => array('mutiple numbers'),
    'type' => MENU_CALLBACK, 
  );
    
  return $items;
}

function myform_sample() {
    $form = array();
    
    // Build up the form
    // See api.drupal.org/?q=api/file/developer/topics/forms_api.html/ (quickstart guide)
    // and api.drupal.org/api/file/developer/topics/forms_api_reference.html (forms api)
    // for more information on creating forms
    
    $form['value1'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 1'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The first value to perform the multiplication with.')
    );
    
    $form['value2'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 2'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The second value to perform the multiplication with.')
    );
    
    // Make sure we have a submit button

    $form['submit'] = array(
		'#type' => 'submit', 
		'#value' => t('Multiple values')
	);

    
    // The name of the form determines the
    // default validation and submit function names
    //
    // In this case
    //    Validation: myform_sample_validate()
    //    Submit: my_form_submit()
    
    return $form;
}

function myform_sample_validate($form, &$form_state) {
    if ( !isset($form_state['values']['value1']) ) {
        form_set_error('value1', t('You must provide the first multiplication value.'));
    }
    else if ( !is_numeric($form_state['values']['value1']) ) {
        form_set_error('value1', t('The first multiplication value must be a number.'));
    }    

    if ( !isset($form_state['values']['value2']) ) {
        form_set_error('value2', t('You must provide the second multiplication value.'));
    }
    else if ( !is_numeric($form_state['values']['value2']) ) {
        form_set_error('value2', t('The second multiplication value must be a number.'));
    }    
}

function myform_sample_submit($form, &$form_state) {
    // Submit routines do not directly produce any output
    // They do something with the form values
    // which is typically to store them in the database
    // then redirect to a path to determine what page is shown next
    
    // In this case the path constructe includes the two values
    
    $form_state['redirect'] = 'myform/multiple/' 
		. $form_state['values']['value1'] . '/' 
		. $form_state['values']['value2'];
}
    

function myform_multiple($value1, $value2) {
    $output = '<p>';
    $output .= $value1. ' * ' . $value2 . ' = ' . ($value1 * $value2);
    $output .= '</p>';
    
    return $output;
}
jsigley’s picture

Thanks steve it worked for me - I agree with everybody else - there is nothing that shows how to implement custom forms correctly.

Now its play time!!!!!

dpembrook’s picture

I wanted to stay on the same page with no redirects and have all the form data available for the function that creates the page. I can then show the form and handle the form results on the same page. The only hack required is one global variable in the module but no changes to the core.

First I adjusted to the menu to call a function in the module for display not call the form API directly. This function, myform_display_page(), calls the form api to build and check the form.

I looked over the form API and didn't see a way to avoid using a global but its limited to one variable I prefixed with the module name to avoid any naming conflicts.

This variable is set in the myform_sample_submit() function that is called when the form is correctly filled out. By testing to see if the variable has been set we can tell if the form passed validation.

Be sure to go to the module list if your updating the previous example. Then give yourself permission to use the module as the name of the permission needed has changed. Browse to /myform to see the form in action.

; $Id$
name = Small Form Sample
description = The myform module multiplies two numbers together
core = 6.x
version = "6.x-1.1"
<?php
/**
* Version: Drupal 6.x
*
* A small example module of using the form api
* to display and process a form
* that is not used to extend the basic node content type
*
* In this sample the form collects two numbers
* and multiplies them together
*/

function myform_display_page() {

	// Start page output
	$page_output = '';
	
	// $myform_form_state will be set in the submit function if the form is properly filled in
	global $myform_form_state;
	
	// Store form output to display later if needed
	$form_output = drupal_get_form('myform_sample');
	
	if (isset($myform_form_state)) {
	
		// form has been correctly submitted
	
		$value1 = $myform_form_state['values']['value1'];
		$value2 = $myform_form_state['values']['value2'];

		$value3 = $value1 * $value2;
		
		// display the result
		$page_output .= '<p>value1: ' . $value1 . ' * ' . $value2 . ' = ' . $value3 . '</p>';	

		// Link back to this page to try again
		$page_output .= '<p>'. l('Try Again', 'myform') . '</p>';
		
	} else {
	
		// The form has not been submitted or there is a form error
		
		// add form output to page output
		$page_output .= $form_output;
	
	}
	
	return $page_output;
}


/**
* Implementation of hook_help().
*
* Throughout Drupal, hook_help() is used to display help text at the top of
* pages. Some other parts of Drupal pages get explanatory text from these hooks
* as well. We use it here to provide a description of the module on the
* module administration page.
*/
function myform_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      // This description is shown in the listing at admin/modules.
      return t('The myform module multiplies two numbers together.');
  }
}

/**
* Implementation of hook_perm().
*
*/
function myform_perm() {
  return array('multiply numbers');
}

/**
* Implementation of hook_menu().
*
*/
function myform_menu() {
  $items = array();

  // This determines the path used to show the form and also makes a menu entry
  // This first path is for the entry form
  $items['myform'] = array(
    'title' => t('sample form'),
	'page callback' => 'myform_display_page',            // drupal_get_form, registers the given form in drupal
    'access arguments' => array('multiply numbers'),
  );

  return $items;
}


function myform_sample() {

    $form = array();
	
   
    // Build up the form
    // See api.drupal.org/?q=api/file/developer/topics/forms_api.html/ (quickstart guide)
    // and api.drupal.org/api/file/developer/topics/forms_api_reference.html (forms api)
    // for more information on creating forms
   
    $form['value1'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 1'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The first value to perform the multiplication with.')
    );
   
    $form['value2'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 2'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The second value to perform the multiplication with.')
    );
   
    // Make sure we have a submit button

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Multiply Values')
    );
 
    // The name of the form determines the
    // default validation and submit function names
    //
    // In this case
    //    Validation: myform_sample_validate()
    //    Submit: my_form_submit()
   
    return $form;
}

function myform_sample_validate($form, &$form_state) {
    if ( !isset($form_state['values']['value1']) ) {
        form_set_error('value1', t('You must provide the first multiplication value.'));
    }
    else if ( !is_numeric($form_state['values']['value1']) ) {
        form_set_error('value1', t('The first multiplication value must be a number.'));
    }   

    if ( !isset($form_state['values']['value2']) ) {
        form_set_error('value2', t('You must provide the second multiplication value.'));
    }
    else if ( !is_numeric($form_state['values']['value2']) ) {
        form_set_error('value2', t('The second multiplication value must be a number.'));
    }   
	
	
}

function myform_sample_submit($form, &$form_state) {
   
    // Set redirect to FALSE to prevent a redirect and make the form data available to your function
   $form_state['redirect'] = FALSE;

  // Copy form state to global variable for use in myform_display_page() after form has been processed in drupal_get_form()
	global $myform_form_state;
	$myform_form_state = $form_state;

}

?>

If anyone has a way around the use of the global, I'd love to hear about it. I'm rather new to Drupal so I've a lot of reading to do to catch up.

eaton’s picture

It sounds like what you want is to set $form_state['rebuild'] = TRUE in your submit handler. That will cause the form to be rebuilt. Your form building function will get a copy of the populated form_state, and there will be no redirection. That'll give you a chance to add additional information in the form building function itself.

--
Lullabot! | Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

dpembrook’s picture

I'm not sure how to get access to $form_state after the redirect. $form_state contains the form values and some other variables (more reading lol)

If I prevent the redirect and save a copy of $form_state I at least have access to all the data without using the form data to create the url on redirect as used in a previous example.

eaton’s picture

The function that actually constructs the form itself -- say, function mymodule_admin_form() {...} or something like that -- gets a copy of the form_state as its first parameter...
--
Lullabot! | Eaton's blog | VotingAPI discussion

--
Eaton — Partner at Autogram

giorgio79’s picture

If you set
'#required' => TRUE

for the form element you don't need those validation options testing for empty fields

demolishun’s picture

<?php
/**
* Version: Drupal 6.x
*
* A small example module of using the form api
* to display and process a form
* that is not used to extend the basic node content type
*
* In this sample the form collects two numbers
* and multiplies them together
*/


/**
* Implementation of hook_help().
*
* Throughout Drupal, hook_help() is used to display help text at the top of
* pages. Some other parts of Drupal pages get explanatory text from these hooks
* as well. We use it here to provide a description of the module on the
* module administration page.
*/
function myform_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      // This description is shown in the listing at admin/modules.
      return t('The myform module multiplies two numbers together.');
  }
}

/**
* Implementation of hook_perm().
*
*/
function myform_perm() {
  return array('mutiple numbers');
}

/**
* Implementation of hook_menu().
*
*/
function myform_menu() {
  $items = array();

  // This determines the path used to show the form and also makes a menu entry
  // This first path is for the entry form
  $items['myform/sample'] = array(
    'title' => t('sample form'),
      'page callback' => 'drupal_get_form',            // drupal_get_form, registers the given form in drupal
       'page arguments' => array('myform_sample'),        // myform_sample, the name of the form to register
    'access arguments' => array('mutiple numbers'),
  );
     
  // This path is for the routine that actually does the multplication
  // It is only setup as a callback (no menu entry)
  $items['myform/multiple'] = array(
    'title' => t('Multiplication Results'),
      'page callback' => 'myform_multiple',            // myform_multiple just returns page text
       'page arguments' => array(2, 3),
    'access arguments' => array('mutiple numbers'),
    'type' => MENU_CALLBACK,
  );
   
  return $items;
}

function myform_sample($form_state) {
    $form = array();
   
    // Build up the form
    // See api.drupal.org/?q=api/file/developer/topics/forms_api.html/ (quickstart guide)
    // and api.drupal.org/api/file/developer/topics/forms_api_reference.html (forms api)
    // for more information on creating forms
   
    $form['value1'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 1'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The first value to perform the multiplication with.'),
      '#required' => TRUE,
      '#default_value' => $form_state['values']['value1']
    );
   
    $form['value2'] = array(
      '#type' => 'textfield',
      '#title' => t('Value 2'),
      '#size' => 4,
      '#maxlength' => 4,
      '#description' => t('The second value to perform the multiplication with.'),
      '#required' => TRUE,
      '#default_value' => $form_state['values']['value2']
    );

    if(isset($form_state['values']['mulresult'])) {
      $form['mulresult'] = array(
        '#type' => 'item',
        '#title' => t('Result'),
        '#value' => t($form_state['values']['mulresult']),
        //'#disabled' => TRUE,
        '#size' => strlen($form_state['values']['mulresult'])
      );
    }
   
    // Make sure we have a submit button

    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Multiply values')
    );

   
    // The name of the form determines the
    // default validation and submit function names
    //
    // In this case
    //    Validation: myform_sample_validate()
    //    Submit: my_form_submit()
   
    return $form;
}

function myform_sample_validate($form, &$form_state) {
    //if ( !isset($form_state['values']['value1']) ) {
    //    form_set_error('value1', t('You must provide the first multiplication value.'));
    //}
    //else 
    if ( !is_numeric($form_state['values']['value1']) ) {
        form_set_error('value1', t('The first multiplication value must be a number.'));
    }   

    //if ( !isset($form_state['values']['value2']) ) {
    //    form_set_error('value2', t('You must provide the second multiplication value.'));
    //}
    //else 
    if ( !is_numeric($form_state['values']['value2']) ) {
        form_set_error('value2', t('The second multiplication value must be a number.'));
    }   
}

function myform_sample_submit($form, &$form_state) {
    // Submit routines do not directly produce any output
    // They do something with the form values
    // which is typically to store them in the database
    // then redirect to a path to determine what page is shown next
   
    // In this case the path constructe includes the two values
   
    //$form_state['redirect'] = 'myform/multiple/'
    //    . $form_state['values']['value1'] . '/'
    //    . $form_state['values']['value2'];
    $form_state['values']['mulresult'] = myform_multiple($form_state['values']['value1'],$form_state['values']['value2']);
    $form_state['rebuild'] = 'TRUE';
    //    . $form_state['values']['value1'] . '/'
    //    . $form_state['values']['value2'];
}
   

function myform_multiple($value1, $value2) {
    //$output = '<p>';
    $output = $value1. ' * ' . $value2 . ' = ' . ($value1 * $value2);
    //$output .= '</p>';
   
    return $output;
}
?>

This is my first step to making my own modules by learning about forms. I have to say I am impressed by the Drupal codebase. I am really impressed by the form functions. Very beautiful design. This is going to work nicely for my site. My favorite is the way it looks when a field is missing and is required. Very professional looking.

Ira Rabinowitz’s picture

I'm a Drupal newbie. Using 6.13. I created and installed myform.info, myform.module and enabled it but I get an error "Page not found" when I go to /myform/sample

bloke_zero’s picture

look at /myform instead - if you look at the navigation menu you'll see it adds a menu item for you.

datawench’s picture

sub

scottbaetz’s picture

Edit by nevets

Folks please do not double post issues and please do not hijack other threads with new issues.

This was a dup of: http://drupal.org/node/409344

Scott Baetz
Web Developer
sbaetz@admininternet.net
AdminInternet
http://www.admininternet.net