These code snippets illustrate how to unset (remove) any undesired form element from a specific form. If you don't want to only remove elements from a form, you can also alter existing values or add new elements to a form using these methods. The example in this lesson uses the Comment form, removing the Your name: <username> (which appears only to logged in users) as well as the title above the textarea of the form. There are two ways you can accomplish this, either using hook_theme() in your template.php, or using hook_form_alter() in a custom module. Both methods are very useful, and you will learn a lot by attempting both.

Using hook_theme() in template.php

Instead of this lesson repeating already existing (and excellent) information, instead please see Using hook_theme() to modify forms and Lullabot: modifying forms. Below is the code for this particular example. Add the following code snippet to your template.php file. Replace MYTHEME with the name of your own theme (e.g. garland) and clear the theme registry after adding the code (see Administer > Site configuration > Performance). Do not include the opening and closing php tags.

<?php
/**
 * Implementation of hook_theme().
 */
function MYTHEME_theme() {
  return array(
    'comment_form' => array(
    'arguments' => array('form' => NULL),
    ),
  );
}


function MYTHEME_comment_form($form) {
  unset($form['_author']);
  unset($form['comment_filter']['comment']['#title']);

  return drupal_render($form);
}
?>

Using hook_form_alter() in a custom module

Many Drupal developers/themers create a small "personal" module to paste or add various bits of code into which have to be applied from a module rather than within the theme template files (some things cannot be modified from the theme layer, while they can be modified from within a module). It's useful to name the module customsite or something along those lines (rather than a site-specific name), as you can then easily recycle the code for future Drupal sites without needing to adjust anything.

If you do not yet have a personal module, you should create one now following the steps below. If you do have a Custom module, simply paste in the function from the code below for altering the form, and you're done.

First make a folder at sites/all/modules/customsite which is where you will save the following two files.

Make a file called customsite.info and paste in the following code:

name = Custom Site functions
description = Custom functions for this site.
core = 6.x
version = "6.x-1.0"

Make a file called customsite.module and paste in the following code:

<?php
// $Id: customsite.module

/**
* @file
* Custom functions for this site.
*/


/**
* Unset these form elements from the comment_form using hook_form_alter
*/
function customsite_form_comment_form_alter(&$form, &$form_state) {
  unset($form['_author']);
  unset($form['comment_filter']['comment']['#title']);
}

In the above code the "Comment:*" title that usually shows directly above the main textarea of the form was also removed using the second unset line (since the text "Post new comment" or "Reply" already shows above the form, removing this extra title helps simplify the form (the textarea does not really need a title: its purpose is already self-evident without the additional text).

After saving these two files, go to Administer > Site building > Modules (admin/build/modules) and enable the new "Custom Site functions" module that you've created. Go view a comment form to ensure that it worked as expected.

You can identify other forms throughout the site and alter them in a similar fashion. Viewing the source of the rendered page in your browser will often reveal the form ID with which you can locate the code in a module that is generating the form. Search the module's code for that ID and it should bring you directly to (or at least close to) the part of the code you wish to alter. More tips on finding the form ID are available in Lullabot's Modifying forms article.

The "Changing Forms with hook_form_alter()" pages of the Pro Drupal Development book are also very helpful in learning more about altering forms.

Comments

fumbling’s picture

Thanks. This was a huge help. I would also like to make the following changes to the comment form. Any idea how? Not knowing much php yet I really can only cut/paste snippets and hope...

    Remove the "Preview" button.
    Change the "Save" label on Save-button to "Post" (without using string overrides, which will make the change everywhere)

I'm also trying to make these same two changes to a create-content form that I built with CCK. The create-content form automatically comes with a form element title that I don't want above each cck field. Is their a similar approach for altering content-creation forms?

Thanks again.

Marko B’s picture

great stuff. would like what else can be done with custom module. can this be done with templating also? (template.php)

to remove other fields and preveiw button
add

unset($form['mail']);
unset($form['homepage']);
unset($form['preview']);

dnewkerk’s picture

I have limited experience with it so far, but yes I think a lot (if not all) can be done in template.php (came up in a recent discussion)...

There's various code examples in that thread, and also here are the links to the lessons:
http://adaptivethemes.com/using-hook-theme-to-modify-drupal-forms
http://www.lullabot.com/articles/modifying-forms-5-and-6

One example I found yesterday of something that couldn't be done this way (again, to my limited knowledge in this area) was adding a #redirect to the contact form (it however works in a module).

In case it helps, here's the snippet I used (in customsite.module):

function customsite_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    case 'comment_form':
      $form['comment_filter']['smileys']['#weight'] = 10;
    break;
  
    case 'contact_mail_page':
      $form['intro']['#value']  = t('This is some text');
      $form['#redirect'] = 'node/2';
    break;
  }
}

I'll update the wording of this documentation page (to explain if/how template.php can be used for this) once I have a stronger grasp on the subject.

drecute’s picture

This is really very helpful. To remove the Preview button from a node creation page, use

<?php 
unset($form['buttons']['preview']);
?>
fumbling’s picture

Btw, you can also use the Jammer module to remove preview buttons and so forth without code in most cases.

msti’s picture

To remove the preview from the comment form create a module and use:

<?php
unset($form['preview']);
?>

Drupal developer and consultant
http://www.mikestiv.com

wickedskaman’s picture

I don't know why I never thought to use unset... this is so much more efficient than hiding gobs of unwanted form data with CSS display:none.

Thanks!!

Steve Ramos
www.zapcrunch.com

gynekolog’s picture

with hook_theme() i get error: Fatal error: Cannot redeclare phptemplate_theme() in MYWAY\template.php on line 60

wickedskaman’s picture

Did you implement hook_theme() as MYWAY_theme() instead of phptemplate_theme()?

Steve Ramos
www.zapcrunch.com

gynekolog’s picture

Yes. But customsite module helped me

dpearcefl’s picture

Should anyone try the hook_theme() route but wind up with the fields and fieldsets in a weird order, please note these comments in modules/node/node.pages.inc:

  // Admin form fields and submit buttons must be rendered first, because
  // they need to go to the bottom of the form, and so should not be part of
  // the catch-all call to drupal_render().

If you copy the function theme_node_form() into your module, change the function name and modify as needed, you will get the desired result.

sano’s picture

I have been searching for some time now for a way to control form elements presence conditionally - based on the role the visiting user has, but could not find any info on this yet. How would I for example:
1) hide certain fields from an anonymous user?
2) display a CCK group to admins only?

Panther256’s picture

In my template.php file I added a function:

<?php
function ramsey_at_theme(){
  if ( user_is_logged_in() ) {
	// do nothing
  } else {
	unset($form['field_archive']);
	unset($form['field_image']);
	unset($form['taxonomy']);
  }

  return array(
    'teen_book_review_node_form' => array(
      'arguments' => array('form' => NULL),
	  'template' => 'node-teen_book_review-edit'
    ),
  );
}

?>

The second section that begins "return aray( ..." allows me to also hook a template file (sits in the same directory as template.php) which does similar functions as the previous code (some things were needed to be done at different levels).

I'm still working on this and I'm not a Drupal guru of any type (presently). It seems to be working the way I wish but I may be missing a render call.

The problem I am having myself is getting a redirect upon submission by the anonymous user and taking them to an acknowledgement page rather than the just created node...

Hope this helps!

- P