Recently a client needed to have a mini form for creating specific types of nodes on the fly from anywhere on the site. So, instead of the user clicking "Create content" then "foo" then filling in the form, then clicking submit, a form for that type of content will be shown on most pages in a block in the side bar. So, they can create that type of node quickly.

There are two ways to do this:

  • Call drupal_get_form('nodetype_node_form'), then use hook_form_alter() to unset the parts you don't need.
  • Create your own form, then do a drupal_execute() using the data from your form.

Calling the node type node form

For this, assuming you have a content type called foo, then you do the following:

function custom_foo_node_form() {
global $user;
$node = array(
'uid' => $user->uid,
'name' => $user->name,
'type' => 'foo',
);
return drupal_get_form('foo_node_form', $node);
}
function custom_form_alter($form_id, &$form) {
if ($form_id == 'foo_node_form') {
if ($_GET['q'] != 'node/add/foo') {
$values = array(
'menu',
'attachments',
'preview',
'options',
'author',
'log',
'body_filter',
'path',
);
foreach($values as $k) {
if (isset($form[$k])) {
unset($form[$k]);
}
}
}
}
} 

You then place the following in a block with type PHP or anywhere in the theme's .tpl.php you wish.

<?php print custom_foo_node_form() ?> 

Using your own form with drupal_execute()

However, in order to keep the mini form clean and not too busy, we opted for the second option.

For this, the code will look like this:

function custom_foo() {
return drupal_get_form('custom_foo_form');
}
function custom_foo_form() {
$form['title'] = array(
'#type'  => 'textfield',
'#title' => 'foo',
);
$form['taxonomy'] = taxonomy_form(1);
$form['submit'] = array(
'#type'  => 'submit',
'#value' => 'Foo',
);
return $form;
}
function custom_foo_form_submit($form_id, $form) {
global $user;
$form_id = 'foo_node_form';
$node = array(
'uid'  => $user->uid,
'name' => $user->name,
'type' => 'foo',
);
$form_values = array(
'title'    => $form['title'],
'name'     => $user->name,
'taxonomy' => $form['taxonomy'],
);
watchdog('debug', 'Saving foo from mini node form');
drupal_execute($form_id, $form_values, $node);
} 

Note that there is no body for this type of node, as it is a CCK type with an optional body. Only the title is relevant. But of course you can include a body if you so wish.

Then, in a block of type PHP or anywhere in your tpl.php files, you place the following call:

<?php print custom_foo() ?> 

Thanks to Karoly Negyesi (chx) for his advice on the options available.

Comments

Tue, 2008/04/22 - 07:04

(Please enable the [blockquote] tag. And please vote to have it recognized by default.)

(And why don't my [code] blocks stand out form the text? And why isn't indentation kept? I almost gave up writing here.)

> return drupal_get_form('foo_node_form', $node);
> ...
> function custom_form_alter($form_id, &$form) {
>   if ($form_id == 'foo_node_form') {
>    if ($_GET['q'] != 'node/add/foo') {

This isn't very elegant. You can alter a form without implemeneting hook_form_alter and without resorting to some magic URL. Simply do:

$form = drupal_retrieve_form('foo_node_form', $node);
// ... manipulate $form ...
drupal_process_form('foo_node_form', $form);
return drupal_render_form('foo_node_form', $form);

I mentioned this technique in a forum post, and I also demonstrated it in some article.

Wed, 2009/08/12 - 11:42

...however you are right, your solution is much more elegant.
Thank you for posting.

Fri, 2008/07/25 - 20:15

I am using Drupal 5.9 and a php newbie. I am using the first example (Calling the node type node form)to add a form in a mini panel on a profile page and no matter what I do, I can't get No matter what I do I can't form_alter function to remove the
'comment_settings',
'menu',
'attachments',
'preview',
'options',
'author',
'log',
'body_filter',
'path'
from the form.

everything else works great, I would just like to hide all of those settings.

Sun, 2008/12/14 - 13:42

 

to me it returns

warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'foo_node_form' was given in Z:\home\wecook.lc\www\includes\form.inc on line 366.

 

what do i do wrong ? using the second way

Thu, 2009/11/26 - 08:13

the code above only works for drupal 5.x - in 6.x there were some changes in form api... i am trying to figure it out myself at the moment, so i can't provide a solution. perhaps the author can?

Fri, 2009/07/03 - 16:44

This is a great tutorial. I was able to implement this and put the form on the left side bar of the site. However, I noticed that my autocomplete fields in the new forms were no longer working. Do you know of a quick fix to this? Looking forward to hearing back, thanks.

Sat, 2010/01/02 - 13:43

Has been renamed to drupal_form_submit() in D7.

Thanks for the guide.

Tue, 2010/04/20 - 06:37

Could you please advise where is the function to be placed? I saved it in template.php, but then it says Fatal error: Call to undefined function and the function isn't found. Shall place it in page.tpl.php directly instead?

Fri, 2010/07/30 - 00:58

Great article you wrote, really inspired me! I wish I can be like you :)

Great article you wrote, really inspired me! I wish I can be like you :)

Pages

Is your Drupal or Backdrop CMS site slow?
Is it suffering from server resources shortages?
Is it experiencing outages?
Contact us for Drupal or Backdrop CMS Performance Optimization and Tuning Consulting