Form API vs straight php
anner - June 9, 2006 - 13:45
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?

sorry, but what is php forms
sorry, but what is php forms ?
----------------
Regards,
Dmitry Kresin, ARDAS group - Web site development, Drupal services, Software development, IT outsourcing.
Reasons for using the Drupal forms API
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.
i tried using forms api but cant seem to know how it works
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
<?php$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
Small form sample
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;
}
?>
thanks for the example, Nevets!
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".
There is a forms api quickstart guide
If I remember correctly it can be found at http://api.drupal.org
-Olegu
http://www.zbz5.net/
Thanks!
Very helpful example.
Ditto
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.
Modifying the edit form. An example, anyone?
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.
Maybe this will help
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;
}
}
I agree with the plea
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 -
<?php
function demo_form_alter($form_id,&$form){
drupal_set_message("Altering '$form_id' <code>".htmlspecialchars(print_r($form,1))."</code>");
}
function demo_install() {
// ensure this always runs AFTER core.modules have done their forms;
db_query("UPDATE {system} SET weight = 3 WHERE name = 'demo'");
}
?>
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.
<?phpfunction demo_form_alter($form_id,&$form){
drupal_set_message("Altering '$form_id' <code>".htmlspecialchars(print_r($form,1))."</code>");
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 :
<?php
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/
Thanks to both of you
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.
Developing is for developers
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.
<?php
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/
Theme forms with form_id
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.
Good point
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/
The reason
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
You can point the form to a
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
Eaton is right. FAPI helps
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.
Thanks for the great example...
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?
Not sure what you are trying to achieve
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 Formdescription = Playpen for form API
Thanks.
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?
If I understand correctly you are trying to add a "buy" button
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).
Coolness
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.
nodeapi view op
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>
The format of $node->content is the same as used by Forms API.
<?php//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/
I got an error when I tried to use the example
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?
Same here, Drupal upgrades
Same here, Drupal upgrades must have broken this...?
Is there a solution?
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.Solution
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
I get an error
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.
Hi, I want to display Create
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
Correct token
<?phpprint 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:
<?php$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.
Thanks for reply.
Hi,
I change in codes as per your suggestion
<?phpprint 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
Success
Hi,
Thanks Heine,
I get success with the codes
<?php$node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
return drupal_get_form($type .'_node_form', $node);
?>
Visit me at http://nashikit.com
To embed an existing form
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.
Form API of Drupal 4.7 is the best for developers...
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
Ok, I see your points, and
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.
A word of advance
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).
I already use this. Thanks
I already use this. Thanks
Ok, if that is the point, I
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.
As a former mambo user/coder...
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
There is another (hidden) problem with using the API...
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?
Honestly speaking, Drupal
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.
Subscribing -- Sharique
Subscribing
--
Sharique uddin Ahmed Farooqui
Web Developer
http://it.Managefolio.com
Subscribing I also have a
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
Hi, im trying to put the
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... :'(
Small Form Sample - Drupal 6.x update
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
<?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 = 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;
}
?>
Thanks steve it worked!!!!
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!!!!!
Small Form Sample - With no redirect (6.x)
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.
$form_state['rebuild'] = TRUE
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
what about $form_state
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.
for buildign function
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
Page not found - Error
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
look at /myform instead - if
look at /myform instead - if you look at the navigation menu you'll see it adds a menu item for you.
http://zero-dev.co.uk
sub
sub
where are my form_state values
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@soscs.net