by Addison Berry on March 17, 2008 // Short URL

Modifying Forms in Drupal 5 and 6

Drupal has a lot of forms to fill out and not all of them may be just the way you want or need them to be. Modifying forms is a topic that is often met with groans but once you understand the two methods to accomplish the task and the basic, underlying concepts, it really isn't that hard to do at all. You'll be a form-modifying, input-customizing wiz in no time. This article will briefly discuss what's going on and then mainly focus on showing working examples for both methods in Drupal 5 and 6. You should be comfortable creating a new function, looking at arrays and a having at least a passing understanding of the Forms API is real handy. Also note that in the examples below I have them wrapped in php tags but you should not include those if you copy/paste. That is just so it looks nice and clear for the article.

Deciding to make the change in the theme or a module

So there are two methods for altering form output in Drupal, one at the theme layer and the other through a custom module. Changes to the HTML can be accomplished with either method so most people will use the method they are more comfortable with already; themers use the theme and developers use a module. There are two situations however where you will want to use a module rather than a theme:

  1. Changing functionality of a form (e.g. adding new validation rules or submission actions) can only happen in a module.
  2. Form elements can be completely removed from the HTML in the theme layer but from an access point of view, someone could still theoretically make use of the field in the form's $_POST because the field is not removed from the form process, only the HTML output is removed. Removing an element in a module can completely remove access to it in any way. This is not often a real problem so removing elements in the theme layer is still acceptable but you should be aware of the distinction.

An example form: User edit

We will not be looking at functional changes here so I'm going to take an example that works well in either method and you can choose the one you prefer. The code is actually quite similar and both rely on two important things: 1) the form's ID and 2) some knowledge of Drupal's Form API.

Our example is altering the form as seen at My Account > Edit in a very simple way to change the name of the Username field from "Username" to say "Login ID" instead.

Find the form ID

All forms in Drupal have a unique ID. You can easily find the form ID in the HTML source code. On your site view the source of the page (Firebug is very handy for this) and look for some hidden fields near the top of the form. One has token stuff in it and another will have the name="form_id". You want to use the value of that form_id input field. In this example it looks something like this (in D5):

<input id="edit-user-edit" type="hidden" value="user_edit" name="form_id"/>

The value for our form ID in this case is "user_edit". In Drupal 6 the form ID is "user_profile_form".

[Note that if you find the form element, e.g. <form id="user-edit" enctype=...) at the top of the form, you will see that is has a very similar id property (in this case "user-edit"). The thing to be aware of is that the form id property uses a hyphen (-) and the form_id that you need for your work has to use an underscore (_).]

Creating your override functions

Now let's start creating the function we will need to hook into the form. Of course, naming and placing the function is slightly different for themes and modules. In all of these examples replace themename and modulename as appropriate. Here is the starting code:

Option 1: Override the theme function

In the theme layer place your function in your theme's template.php file. You will create a new function for each form you wish to modify.
D5 theme override

<?php
 
/**
   * Theme override for user edit form.
   *
   * The function is named themename_formid.
   */
 
function themename_user_edit($form) {
   
// Our kickin' mods go here.
 
}
?>

D6 theme override
In D6 theming this gets interesting. Many forms in D6 now have template files or "registered" functions. For those you can simply edit the .tpl file or override the function as in D5, respectively. For forms that do not have templates or registered functions though, we need to not only create the override function but we also need to register it with the theme system so it knows about it. For more information on this see the handbook page about using the theme registry for special cases. Our user edit form is one such beast. Once you add the following functions to your template.php, reset the the theme registry by clearing cached data on the Administer > Performance page.

Here is the theme registry function we need:

<?php
/**
* Implementation of hook_theme.
*
* Register custom theme functions.
*/
function themename_theme() {
  return array(
   
// The form ID.
   
'user_profile_form' => array(
     
// Forms always take the form argument.
     
'arguments' => array('form' => NULL),
    ),
  );
}
?>

And here is the override function; very much like the D5 version except the form ID.

<?php
 
/**
   * Theme override for user edit form.
   *
   * The function is named themename_formid.
   */
 
function themename_user_profile_form($form) {
   
// Our kickin' mods go here.
 
}
?>

Option 2: Use hook_form_alter() in a module

D5 hook_form_alter()
If using a module, place the hook_form_alter function (D5 and D6) in your .module file. You will use this one function to change as many forms as you want, using the form ID in a switch statement for each one.

<?php
 
/**
   * Implementation of hook_form_alter().
   *
   * The function is named modulename_form_alter.
   */
 
function modulename_form_alter($form_id, &$form) {
   
// Normally a switch is used because you may want to alter more than
    // one form and it is easy to add a new case for each form.
   
switch ($form_id) {
     
// This is our form ID.
     
case 'user_edit':
       
// Our kickin' mods go here.
       
break;
    }
  }
?>

D6 hook_form_alter()

<?php
 
/**
   * Implementation of hook_form_alter().
   *
   * The function is named modulename_form_alter.
   */
 
function modulename_form_alter(&$form, $form_state, $form_id) {
   
// Normally a switch is used because you may want to alter more than
    // one form and it is easy to add a new case for each form.
   
switch ($form_id) {
     
// This is our form ID.
     
case 'user_profile_form':
       
// Our kickin' mods go here.
       
break;
    }
  }
?>

Viewing the $form array

Once you have gotten the form ID and created the function you will need to see the existing form elements you have to work with. If you have Devel module enabled, you can use the shorthand dsm() function to pretty print the $form array. Otherwise a regular PHP print_r() or var_dump() will work fine. Whichever function you use to see the array, place it in your function where the code above says "// Our kickin' mods go here." For example:

<?php
 
function themename_user_edit($form) {
    return
print_r($form);
  }
?>

When you reload the page with the form on it now you should see a whole bunch of yummy array output. If not, make sure you got the form_id correct and that you have named your function properly.

Find the form element and property

There is quite a bit of documentation on FAPI and I'm not going to dive very deeply here. Here are the quickstart guides for D5 and D6. You may also want to have a handy bookmark to the form property reference, D5 and D6.

Basically we are going to look at the $form array, find what we want to change and translate that into FAPI for our function. Let's look at a section of the $form array that I am seeing on my site:

Array
(
  [account] => Array
  (
    [#type] => fieldset
    [#title] => Account information
    [name] => Array
    (
      [#type] => textfield
      [#title] => Username
      [#weight] => 0
      [#maxlength] => 60
      [#description] => Your preferred username; punctuation is not allowed except for periods, hyphens, and underscores.
    )
  )
  [pass] => Array
  (
    [#type] => password_confirm
    // snip...
  )
  // snip...
  [comment_settings] => Array
  (
    [#type] => fieldset
    [#title] => Comment settings
    [#collapsible] => 1
    [#collapsed] =>
    // snip...
  )
)

So basically we need to walk down the array to find the part we want to change. I want to change the title of the Username field. Looking at my array that means I want to target [account][name][#title]. Once I find that, I can just put that in my function and tell Drupal what I want to do with it. If you aren't sure what you can do to a given property, looking at the reference chart linked to above will help out.

$form['account']['name']['#title'] = t('Login ID');

I can do this with any of the FAPI properties. For example I can set the default value of a fieldset to collapsed:

$form['comment_settings']['#collapsed'] = TRUE;

Or I can even remove an element entirely using the unset function. This would remove the Signature text area from the form:

unset($form['comment_settings']);

So, go have fun and get those rascally forms just the way you want them!

Full example functions

Here are the complete, commented example functions.

Theme override: D5

<?php
/**
* Theme override for user edit form.
*
* The function is named themename_formid.
*/
function themename_user_edit($form) {
 
$output = '';
 
// Print out the $form array to see all the elements we are working with.
  //$output .= dsm($form);
  // Once I know which part of the array I'm after we can change it.

  // You can use the normal Form API structure to change things, like so:
  // Change the Username field title to Login ID.
 
$form['account']['name']['#title'] = t('Login ID');

 
// Make sure you call a drupal_render() on the entire $form to make sure you
  // still output all of the elements (particularly hidden ones needed
  // for the form to function properly.)
 
$output .= drupal_render($form);
  return
$output;
}
?>

Theme override: D6

Theme registry function:

<?php
/**
* Implementation of hook_theme.
*
* Register custom theme functions.
*/
function themename_theme() {
   return array(
    
// The form ID.
    
'user_profile_form' => array(
      
// Forms always take the form argument.
      
'arguments' => array('form' => NULL),
     ),
   );
}
?>

Form override function:
<?php
/**
* Theme override for user edit form.
*
* The function is named themename_formid.
*/
function themename_user_profile_form($form) {
 
$output = '';
 
// Print out the $form array to see all the elements we are working with.
  //$output .= dsm($form);
  // Once I know which part of the array I'm after we can change it.

  // You can use the normal Form API structure to change things, like so:
  // Change the Username field title to Login ID.
 
$form['account']['name']['#title'] = t('Login ID');

 
// Make sure you call a drupal_render() on the entire $form to make sure you
  // still output all of the elements (particularly hidden ones needed
  // for the form to function properly.)
 
$output .= drupal_render($form);
  return
$output;
}
?>

Module hook_form_alter(): D5

<?php
/**
* Implementation of hook_form_alter().
*
* This lets you make changes to any form in the site. You can alter, remove
* or add form elements. You can also alter the validation and submission
* behavior. The name will always be modulename_form_alter.
*/
function modulename_form_alter($form_id, &$form) {
 
// Normally a switch is used because you may want to alter more than
  // one form and it is easy to add a new case for each form.
 
switch ($form_id) {
   
// This is our form ID.
   
case 'user_edit':
     
// Print out the $form array to see all the elements we are working with.
      //$output .= dsm($form);
      // Once I know which part of the array I'm after we can change it.
     
      // Change the Username field title to Login ID.
     
$form['account']['name']['#title'] = t('Login ID');
      break;
  }
}
?>

Module hook_form_alter(): D6

<?php
/**
* Implementation of hook_form_alter().
*
* This lets you make changes to any form in the site. You can alter, remove
* or add form elements. You can also alter the validation and submission
* behavior. The name will always be modulename_form_alter.
*/
function modulename_form_alter(&$form, $form_state, $form_id) {
 
// Normally a switch is used because you may want to alter more than
  // one form and it is easy to add a new case for each form.
 
switch ($form_id) {
   
// This is our form ID.
   
case 'user_profile_form':
     
// Print out the $form array to see all the elements we are working with.
      //$output .= dsm($form);
      // Once I know which part of the array I'm after we can change it.
     
      // Change the Username field title to Login ID.
     
$form['account']['name']['#title'] = t('Login ID');
      break;
  }
}
?>

Addison Berry

Director of Education

Want Addison Berry to speak at your event? Contact us with the details and we’ll be in touch soon.

Comments

John Lewis

Forms always confuse me.

I'll have to go over this line by line to understand it. Particularly the code section where they have such a strange way of representing forms.

Reply

Jahangir

Very valuable

Excellent post that helps us understand overriding forms and create custom forms.

Reply

lee

The missing piece to the puzzle!

Terrific! You're saving a lot of people agony, time and angst. Thanks for clarifying a woefully underdocumented yet crucial part of how Drupal works.

Reply

msonnabaum

Awesome!

Great article! Couldn't have come at a better time too.

I needed to figure out how to substitute user profile fields in a user reference field rather than usernames (since I use LDAP for authentication), and this is a much simpler solution than I was considering.

Here's what I came up with:

<?php
function themename_node_form($form) {
 
$output = '';
  foreach (
$form['field_instructor_pref_first']['uids']['#options'] as $uid => $username) {
   
$form['field_instructor_pref_first']['uids']['#options'][$uid] =  t('!first !last', array(
     
'!first' => user_load(array('uid' => $uid, 'status' => 1))->profile_firstname,
     
'!last' => user_load(array('uid' => $uid, 'status' => 1))->profile_lastname)
    );
  }
 
$output .= drupal_render($form);
  return
$output;
?>

Thanks again!

Reply

feelexit

got a question.

this is a great tutorial. I want to customize my forum comment reply form.

<div class="box">
    <h2 class="title">Reply</h2>   
   
    <div class="content">
    <form action="/mom/comment/reply/5"  method="post" id="comment-form">

I want to remove

Reply

, but this is not in the array. is there a way to remove it?

Reply

addi

comment.tpl.php

That is coming from your comment.tpl.php file. So you can edit it there directly.

Reply

Anonymous

you cannot change it in

you cannot change it in comment.tpl.php file.

<div class="content">
    <?php print $content ?>
  </div>

$content contains that code.

Reply

addi

Urgh, sorry - box.tpl.php

Comments are printed inside boxes so you need to use box.tpl.php. Sorry about the misdirection there.

If your theme does not already have a box.tpl.php file you can override the default one by creating one for your theme, using the default one as a template. The default tpl (for D5) can be found at themes/engines/phptemplate/box.tpl.php. In D6 it is located at modules/system/box.tpl.php.

Reply

feelexit

thank you addi

thank you so much. cannot believe I didnt figure out i should change box.tpl.php file.

Reply

tjholowaychuk

Themer

I would like to point out to users that the 'themer' module provides body classes by role, path, locale, etc.

This is useful in the case of forms because if you need to hide the input format field for users of a certain role you can achieve this with this simple selector:

body.role-manager fieldset.input-format {
display: none;
}

etc, which is useful for un-cluttering portions of forms very quickly. Keep in mind that if you do not wish them to have access to these fields at all then this is not the way to go.

Reply

Sprugman

custom validation for user form

I'm trying to require a checkbox be checked on the user registration form in D6. In D5, I would have done something like:

<?php
function myModule_form_alter($form_id, &$form) {
  if (
$form_id == 'user_register' || $form_id == 'user_edit') {
   
$form['FormSection']['profile_myCheckbox']['#validate'] =
      array(
'myModule_myCheckbox_validate' =>
        array(
$form_id, $form));
  }
}
?>

(sorry about the awkward wrappng.)

I can't seem to figure out the equivalent in D6....

Reply

addi

#validate changed in D6

In D5 #validate could be used for both elements and the form itself. This was changed in D6 so that validating an element is now #element_validate and #validate is only used for the form-level validation. So you need to use #element_validate in your example for D6.

Reply

feelexit

another newbie question, how to restyle forms?

I try to restyle comment reply form.

here's part of the code:

<div class="form-item">
<label>your name: </label>

<a href="/mom/user/1" title="View user profile.">feelexit</a>
</div>

right now, "your name" is one line, name input box is on another line, I want to make them one line. what I did right now is to put styles in style.css, make label display inline.

I want to know, if theres a way to change code to

<div class="form-item">
<span style="font-weight:normal;">your name: </span>

<a href="/mom/user/1" title="View user profile." style="text-decoration:underline;">feelexit</a>
</div>
Reply

Anonymous

I have the same question on

I have the same question on theming forms so that elements don't wrap lines but stay on the same line. Any suggestions?

Reply

Dirk Gebhardt

render form in D5 with tiny etc

Hi All,

i am trying to render a from in Drupal 5 with all its attributes. My problem is i can render the form like drupal_render($form['group_index']['field_awards'][0]['value'] but this dosn´t give me the tinyMCE wtih the form if i try do go like drupal_render($form['group_index']['field_awards'][0]['value']['#process']['tiny_etcect'] nothing will happen.

Does anyboddy has an suggestion for me?

Dirk

Reply

addi

Maybe a part 2

Sounds like that would be a good follow up article. I'll see what I can do.

Reply

gausarts

Can't wait to see the tut

Can't wait to see the tut part 2 as well, especially adding fields to comment form and outputting it into the template, perhaps a specific comment_form, if you don't mind. Thanks

Reply

omnyx

profile form field hidden on edit page

First, thank for the great writeup!
I would like to create a textfield in which I can assign (type) different titles to users. That field should be hidden from users when they click 'edit' on their profile (but I, or the user admin, can still see and edit it there) and visible to everyone on the user profile view page.

I was thinking of finding the form field name within the form with the user-edit id and setting that field to hidden (except for the admins). Can I do that in the form attributes?

If not, what would you suggest?
Thanks!

Reply

addi

Yes

You can set any FormAPI property. So you can put an if statement around the change in your modification function and set the element's '#type' => 'hidden'.

Reply

omnyx

So, in user-edit (within a

So, in user-edit (within a custom module) I just put:

$form['Personal Information']['profile_year']['#type']='hidden';

and it works, i.e. the year is displayed only on the profile view page and not on the profile edit page.
A quick question: When would I use '=>'and when '=' when assigning form properties?
Could you direct me to a link where I could read more about this?

Thanks and thanks for the great article!

Reply

addi

=> is for use inside an array

so if you were setting an element with an array you use =>.

<?php

$form
['foo'] = array(
 
'#type' => 'hidden',
 
'#title' => t('My foo thing'),
);
?>

The = is for straight assignment of a single property in the array.

<?php
$form
['foo']['#type'] = 'hidden';
?>
Reply

maanas

preg match error

Hi,
First this is great tutorial on using the hook_form_alter. I am using this concept on many projects I am working on.
I believe this is one thing which will push drupal in top of the league of frame works. I just create a module_form_alter.module for my project and then separate functions for the all the altering I require. Once it is on the site is running into the required mode.

I am encountering one strange warning when I am trying to alter the user_register form. I want to change the widget from check boxes to radios so that only one role can be given to users.

case 'user_register':
$form['roles']['#type'] = 'radios';


warning: preg_match() expects parameter 2 to be string, array given in includes\bootstrap.inc on line 771.

I checked up the bootstrap.inc it is doing a check for utf-8.

Can any one throw some light why this behavior?

Reply

Anonymous

Hide the password fields for LDAP-auth sites

This is an excellent article. I've been having fun tweaking a module to edit for fields. Here's the best application of this technique I've found so far:

We authenticate users by LDAP (w/ LDAP Integration module). So I don't want users going to their user//edit form, filling out a password field, and then calling the helpdesk when they can't log in with their "changed" password. Solution:

function ulaw_utils_form_alter($form_id, &$form) {
  switch ($form_id) {
    case 'user_edit':
        // hide the password thingy, we're using LDAP! (except for admin)
        if ($GLOBALS['user']->uid != 1) {
          $form['account']['pass'] = array(
            '#title' => 'Password',
            '#type' => 'item',
            '#description' => t('To change your password for this site, you must '.
              l('change your LDAP password.', 'https://ldap/password/form/url'),
          );
        }
        break;
  }
}

This will save us a lot of user education. (for various reasons, I can't use the password-changing feature of LDAP integration, which would be the simpler solution!)

Reply

pouderstream

Posting form modification from 'View' page via Ajax?

First tnx, for great explanation.
Ok then. I've got a form on a user profile page (I made a new content type with nodeprofile module and added CCk field) 'View' tab witch I want to modify with custom ajax defined in node-myContentType.tpl.php page witch I've overriden.

Now the problem is that not only I need to modify data, I also had to read new data from response. Any suggestion? Or should I make custom queries from $node object info.? So my problem is, what fns or. query to call? Collecting data and sending them via ajax isn't problem here.

IDEA(in steps):

1.(client)send modifiedValue
   - (server?)oldData + modifiedValue = Sum (write that to database)
   - (server?)echo Sum
2.(client)Update current Sum field

client --> current page (e.g. JavaScript in it)
server --> page I'm sending request to.This is problematic.I don't know where?

Oh.I need custom JS because I'll refresh few other parts on this page based on response value.
Any hint would be grea, tnx.

p.s.I'm only month with Drupal, so bear with me plz ;)

Reply

pouderstream

Ok, I'll do a module ;)

You said in beggining that one can only modify data in module. I think it's getting clearer to me. I'll make a kind of helper module for this. It should work I think.
I'm watching http://drupaldojo.com/node/73 lesson now on using jQuery and I'll work something out with that. ;)
Again, tnx for great article.

Reply

peashooter

Does this hold true for comment forms?

Hi,

Great tutorial. However, is this for non-comment forms? I can't seem to use the above tutorials to customise my comment form.

I've tried using hook_comment in my module file but if I put:

<?php
return print_r($form);
?>

after

<?php
case 'form':
?>

part it seems to gibber... any ideas?

Reply

addi

Wrong code

You aren't following this tutorial - hook_comment is an entirely different thing that what this tutorial is covering.

Reply

peashooter

bit harsh?

I was following the tutorial actually. I've tried using hook_form_alter to change the comment form, and I got the same result.

There is no 'name' like the other forms for the comment form.

If comment forms can't be modified using this tutorial it might help to make that clear because I couldn't find that information anywhere.

Sorry if this isn't all immediately obvious, but I'm still learning here - that's why I'm using tutorials!

Reply

addi

I didn't intend to be harsh

I didn't intend to be harsh at all, but just wanted to point out that hook_comment is a totally different thing that what this tutorial covered so I wasn't sure how that applied to this. When I look at the comment form HTML I can see the ID is comment_form. Remember that you are looking for the "value" of the input that is named "form_id", not the "name." The following code gives me the form array for the comment form in D5:

<?php
function modulename_form_alter($form_id, $form) {
  switch (
$form_id) {
    case
'comment_form':
     
print_r($form);
      break;
  }
}
?>
Reply

Peashooter

Thanks

Cheers for that, great help.

Reply

Steve

I'm trying to use this

I'm trying to use this approach to modify the admin settings form for the Nice Menus module to allow an arbitrary number of menus instead of the 10 that are hardcoded into the module. I'm using hook_form_alter to modify the nice_menus_admin_settings form. The problem I'm having is that I'm unable to modify the form for some reason. I know I've identified the form properly because if I do a print_r($form), the form array is printed out.

Here's what I have:

/**
* Implementation of hook_form_alter()
*
* Modify the admin settings for nice_menus module to allow
* an arbitrary number of menu blocks
*/
function cwl_form_alter($form_id, &$form) {
  switch ($form_id) {
  case 'nice_menus_admin_settings':
$form['nice_menus_number']['#type'] = 'textfield';
break;
}
}

?>

So what I'm trying to do is change the select list to a text field. However, this has no effect. I've also tried just replacing the whole array for this field:
/**
* Implementation of hook_form_alter()
*
* Modify the admin settings for nice_menus module to allow
* an arbitrary number of menu blocks
*/
function cwl_form_alter($form_id, &$form) {
  switch ($form_id) {
  case 'nice_menus_admin_settings':
            $form['nice_menus_number'] = array(
              '#type' => 'textfield',
              '#title' => t('Number of Nice Menus'),
               '#description' => t('The total number of independent nice menus (blocks)                 you want.'),
              '#default_value' => variable_get('nice_menus_number', '2'),
  );
}
}

?>

Is that doable? Is there something obvious I'm missing?

Thanks.

Reply

addi

Module weight

This is one of those weird gotchas. Your module is running before Nice Menus because by default they run in alphabetical order. You can change the weight of your module to 1 to make it run after NM and then it should fire correctly. This is in the system table, weight column.

Also, this feature is actually part of the D6 version of Nice menus and could easily be backported to Drupal 5. If you make a patch, I'd be willing to commit it. ;-)

Reply

Mike Kay

Modifying Drupal Search

I am on the low edge of the curve with hooks and modifying Drupal with functions, and your explanation demystifies a lot. Thanks...

I am modifying a form which is already registered (in Drupal 6), the Theme Search Form (just trying to alter/remove the label), so it works a little differently. Following your instructions, it ends up printing the form twice, the original version and the modified one. Then when I create a search-theme-form.tpl, I seem to fall short on the correct syntax to use there.

This is the array in the core search module that I am trying to modify:
$form[$form_id] = array(
'#title' => t(''),
'#type' => 'textfield',
'#size' => 15,
'#default_value' => '',
'#attributes' => array('title' => t('Enter the terms you wish to search for.')),
);

This should be really simple but for some reason I keep falling short. Can anyone point me to the best way to do this, ... or any way. ;) thanks

Reply

eaposztrof

module do nothing..

hi all..
i have some working personal module, but the "e_reg_form_alter" doo nothing..
i try this:

<?php
function eaposztrof_signup_form_alter($form_id, $form) {
  switch (
$form_id) {
    case
'user-register':
     
print_r($form);
      break;
  }
}
?>

the module name and filenames is "e_reg" too.. and the drupal is the newest 6.2..
any ideea? Reply

Anonymous

sorry..

the correct code from the enabled module is:

<?php
function e_reg_form_alter($form_id, $form) {
  switch (
$form_id) {
    case
'user-register':
     
print_r($form);
      break;
  }
}
?>

why not working? Reply

addi

Different parameters

Hey there,

The parameters changed in D6 so make sure you are using the right version of the code. What you have there is for D5. The parameters in D6 are &$form, $form_state, $form_id.

Reply

RyanW

This is very helpful, just one question

I agree, this is an extremely helpful tutorial, thank you for writing it. I'm wondering if there's a way in D6 to do the override, but keep the .tpl.php file in the loop. Like the tutorial, if I want to change a form field's label, I know I can do :

function phptemplate_search_block_form($form) {
  $output = '';
  $form['search_block_form']['#title'] = t('Some new title');
  $form['submit']['#value'] = t('Some new button value');
  $output .= drupal_render($form);
  return $output;
}

But any other markup in the .tpl.php file is ignored. So, am I understanding this right that if you do the override function in a theme's template, you effectively take the .tpl.php file completely out of the loop? I was hoping I could just modify the values somewhere in the stack, but keep .tpl.php for rendering. Maybe a preprocess function or something?

Reply

Steve

This is appreciated - thanks

Forum topics don't really need teaser's on my site. This article was really helpful in removing the Teaser field when submitting new topics. Thanks.

Reply

omnyx

Upon checking the box profile field becomes uneditable

First, thanks for the great writeup!
I used your code to do the following: Using profile module I created a 'verified user' (profile_verify) checkbox field which is visible only to admins/themes. I want that, upon checking the box (by admin), the email field becomes uneditable.

I got it to work, and all is fine but I just want to be sure that what I did is valid and makes sense (in terms of code)

<?php
function formxyz_form_alter($form_id, &$form) {
  global
$user;
  switch (
$form_id) {
    case
'user_edit':
      if (
$form['_account']['#value']->profile_verify=='1') {
    
$form['account']['mail']['#attributes']=array('readonly' => 'readonly');  
     }
      break;
  }
}
?>

again, it works fine, but is that the way to go?
thanks!

Reply

B.S.Bharanikumariyer

how to store the form_alter field values

Hi

I added the text box in the user registration form using the form_alter,

Now tell me , how i store the this textfield values into table,

I thing i have to write some snippet in the INSTALL file also,

Can u tell me please

the below is my code, i want to store the below field values into DB

function user_form_alter($form_id, &$form) {
  if ($form_id == 'user_register' || $form_id == 'user_edit') {
  $form['fname'] = array(
  '#type' => 'textfield',
  '#title' => t('First Name'),
  '#default_value' => $node->title,
  '#size' => 60,
  '#maxlength' => 128,
  '#required' => TRUE,
   );
   $form['lname'] = array(
  '#type' => 'textfield',
  '#title' => t('Last Name'),
  '#default_value' => $node->title,
  '#size' => 60,
  '#maxlength' => 128,
  '#required' => TRUE,
   );
    $form['reset'] = array(
      '#value' => '<input class="form-button" type="reset" value="Reset" />',
      '#weight' => 1001,
    );
  }
}
Reply

brunodbo

Wow, thanks so much for this

Wow, thanks so much for this article! I learnt a lot today.

Here's what I needed to do:

On our site, both anonymous and registered users are allowed to create nodes. We allow them to provide multiple authors for content, so that if a report was made by several people, they can all get proper credit for it.

Anonymous users can fill in their name in a CCK text field; registered users fill in a nodereference field. Both of these fields are required. Hiding one or the other field from one or the other user role is done with cck_field_permissions.

The problem: when admins (who have access to the text field as well as the nodereference field) want to edit a node, they got a validation error, because both fields are required, and one of them is often empty.

Solution: a module that un-requires both fields for admin roles.

<?php
function modulename_form_alter($form_id, &$form) {
  switch (
$form_id) {
    case
'article_node_form':
      global
$user;
     
$allowed = array('admin','edito');
      foreach(
$user->roles as $role) {
        if (
in_array($role, $allowed)) {
         
$form['field_author_reg']['0']['user_name']['#required'] = 0;
         
$form['field_author_anon']['0']['value']['#required'] = 0;
        }
      }
    break;
  }
}
?>
Reply

Hello Kitty

field title change not reflected in preview and view of form

Hi,

I am trying to over-ride the comments form for our drupal 5.8 site. I need to change "Subject" to "Re". I can do this using hook_form_alter:

function hook_form_alter($form_id, &$form) {
switch ($form_id) {
case 'comment_form' :
$node = node_load($form['nid']['#value']);
$subject = $node->title;
$form['subject']['#title'] = "Re";
$form['#submit']['external_page_comment_form_submit'] = array($subject);
$form['#submit'] = array_reverse($form['#submit']);
return $form;
}
}

The problem is that the change doesn't seem to carry over to previewing or posting the comment. The subject label reverts back to "Subject".

I think that I also have to change the subject label in hook_comment but I am not sure how to do this. Can I use the same form api syntax as in hook_form_alter?

Here is what I have in my hook_comment:

function hook_comment(&$comment, $op) {
switch ($op) {
case 'view':
if (variable_get('vote_up_down_widget_comment', 1)) {
//print_r($comment);
$comment->comment = $comment->comment ."". theme("external_page_points_alt", $comment->cid, 'comment') ."";
$comment->comment = $comment->comment . theme("external_page_widget_alt", $comment->cid, 'comment');
}
break;
}
}

I am using vote-up-down and have been able to insert the point info at the bottom of comments, before the comment $links.

I can't seem to figure out how to get at the stuff at the beginning of comments, it's all lumped in $comment->comment.

Thanks for this article and thanks to anyone who can point me to more examples of bending comment forms to my will :-)

Reply

Anonymous

Excellent!

Thank's a lot for this tutorial! It's just excellent - and unique!

Do you know if there is a chance to access $node contents within a theme function (option 1)?

What I'm trying to do is to modify the form which is used to add a comment. If I am in a special forum, I want to have a special layout of this form.

So I am overriding the comment reply form (comment_form) which works fine. I just have to check if the user is adding a comment to a topic in that specific forum. Just: how to find out about this? The easiest way is to check the taxonomy term of the parent article. And therefore, access to $node would be nice :-)

Thanks, Gerald

Reply

adampasz

Fantastic!

After sifting through so much confusing Drupal documentation, this article is a real breath of fresh air. Thank you for your thoroughness!

Reply

Martin Q

Get the right ID!

Hello.

This is an awesome tutorial - thanks.

Just to clarify something which fooled me for a while. You appear to suggest that using the id attribute from a tag like

<form action="/node/61/edit"  accept-charset="UTF-8" method="post" id="node-form" enctype="multipart/form-data">

is possible, as long as one turns the '-' into a '_'. This is not true (and may not be what you meant to imply). The correct id we require is found in a tag like

<input type="hidden" name="form_id" id="edit-modulename-node-form" value="modulename_node_form"  />

(in this case, the id is modulename_node_form).

If I spent half an hour trying to work my mistake out, I am sure others will appreciate this being cleared up too.

Apart from that, thanks again for this fantastic tutorial.

Reply

Andrew

Trouble with weight

I don't know if I'm doing something wrong, or if I need to submit a bug report on this one. Figured I'd start here since this is where I got the info...

function fblike_theme() {
   return array(
     'node_form' => array(
       'arguments' => array('form' => NULL),
     ),
   );
}
function fblike_node_form($form) {
if (arg(2) == 'profile') {
  $form['field_first_name']['0']['value']['#size'] = 25;
  $form['title']['#size'] = 25;
  $form['field_age']['value']['#description'] = 'testf';
  $output .= drupal_render($form); }else{
  $output .= drupal_render($form);
  }
  return $output;
}

So that's just some test to see how everything was working, and it worked fine. However, the weight (now operated by the jquery drag and drop) gets all messed up. The form submit, preview, and menu options appear at the top of the node regardless of changes to the "manage fields" and clearing all cache.

Is this incompatible? Suppose to happen? Do I need to define the weight? Anyone having the same problem?

Thanks! - besides this error, the tutorial helped a ton.

Reply

Andrew

More Info

So, if I define the weight it works fine. Who knows that the problem is, but defining the weight will work fine for me. I'm still sure there must be a way to retain the weight as defined in the manage fields tab.

Reply

Steve

I have the same problem...

I'm trying to arrange the elements on various node edit forms (so the id for each form is 'content_type_node_form').

I first created a module called 'customize_forms', and it worked for some form elements, but not all form elements. Then I read in one of the comments here that modules are run in alphabetical order, so I changed the name to 'zzz_forms'.

This helped, and now I could change the weight for more elements, but not all of them. On top of that, even though I can change the weight for more form elements, they still don't actually change position on the form.

Here's my module's code:

<?php
// $Id$
/**
* @file
* This module is used to customise form alterations, easily.
*/

/**
* Implementation of hook_form_alter().
*
* This lets you make changes to any form in the site. You can alter, remove
* or add form elements. You can also alter the validation and submission
* behavior. The name will always be modulename_form_alter.
*/
function zzz_forms_form_alter(&$form, $form_state, $form_id) {
// Normally a switch is used because you may want to alter more than
// one form and it is easy to add a new case for each form.
switch ($form_id) {
// This is our form ID.
case 'profile_elected_node_form':
case 'profile_constituent_node_form':
case 'profile_committee_node_form':
case 'profile_candidate_node_form':
case 'poll_node_form':
case 'page_node_form':
case 'image_node_form':
case 'header_panoramic_node_form':
case 'forum_node_form':
case 'event_calendar_node_form':
case 'blog_node_form':  
if ($form['revision_information']) {
        // Remove 'Revision Log message' text area
  $form['revision_information']['#type'] = 'hidden';
      }
      if ($form['taxonomy']) {
        // Change titles of form elements
$form['taxonomy']['#title'] = t('Categories');
      }
      if ($form['workflow']) {
        // Adjust form weight.
$form['workflow']['#weight'] = 40;
      }

      if ($form['path']) {
        // Adjust form weight.
$form['path']['#weight'] = 60;
      }

      if ($form['menu']) {
        // Adjust form weight.
$form['menu']['#weight'] = 70;
      }

      if ($form['nodewords']) {
        // Adjust form weight.
$form['nodewords']['#weight'] = 80;
      }

      if ($form['xmlsitemap']) {
        // Adjust form weight.
$form['xmlsitemap']['#weight'] = 80;
      }

      if ($form['author']) {
        // Adjust form weight.
$form['author']['#weight'] = 90;
      }

      if ($form['options']) {
        // Adjust form weight.
$form['options']['#weight'] = 100;
      }
     
// Show form elements and weights.
// Code borrowed from Devel module.
    $children = element_children($form);
    /*
    print '<pre>';
    print_r($children);
    print '</pre>';
    */
if (empty($children)) {
if (isset($form['#type']) && !in_array($form['#type'], array('value', 'hidden'))) {
if (!isset($form['#title'])) {
$form['#title'] = '';
}
$form['#title'] .= " (key=$key_in, weight=". (isset($form['#weight']) ? $form['#weight'] : 0) .')';
}
}
else {
foreach (element_children($form) as $key) {
// We need to add the weight to fieldsets.
if (element_children($form[$key])) { // Which are a container of others.
if (!isset($form[$key]['#title'])) {
$form[$key]['#title'] = '';
}
$form[$key]['#title'] .= " (key=$key, weight=". (isset($form[$key]['#weight']) ? $form[$key]['#weight'] : 0) .')';
}
}
}

// Print out the $form array to see all the elements we are working with.
/*
print '<pre>';
print_r($form);
print '</pre>';
*/
break;
}
}

Here's a link to a screen shot.
http://www.wickwoodonline.com/content/example-weight-problems-node-edit-...

On it you can see that 'Menu' given a weight of 70 from my module, still appears with the 30 weights. Also, CCK fields don't seem to have weight associated with it all, so those form elements are being added after my module.

I tried using the module 'late_form_alter', but this didn't solve anything for me.

Thanks for any help you can give me in advance!
Steve

Reply

Aruna

How to find a particular form..

Actually I want to modify "Body" field Blog edit form. I want to try out Google API to translate the content of blog written in English to Chinese on this page.
I took it's source and found

So as per the your article, my form will be "blog_node_form". I tried to find it, but didn't get any where in Drupal package.

I am new (just 2 days on Drupal) to Drupal. May I know how I can find this form and modify it?

Thanks in advance,

Reply

PinaySpeak

thanks

thanks for this tips.. now i know how to do it... thanks its help me alot..

Reply

Andy

how do I access the value of my custom field?

Thanks for the nice tutorial. I've added a couple custom fields to my comment form. Much like this very comment form I'm filling out now: "Name" with a title of 'commentor_name' and "E-mail" with a title of 'commentor_email'. This works fine and the fields show up when filling in the comment.

My question however is, now how do I get access to the values that the user filled in? How do I make the comment node display something like this page does, e.g.

"Submitted on September, 28 by "? Do I have to do my own custom database store of the Name and Email fields or does the comment module do that for me? What file do I have to override in order to output those values when viewing the comments?

Thanks,
Andy

Reply

Andy

Oops, mangled output

I wrote a custom module to achieve this, here's the code:

function authored_comment_form_alter(&$form, $form_state, $form_id ){
   switch($form_id){
      case 'comment_form':
      //print_r($form);
      $form['commentor_name'] = array(
        '#type' => 'textfield',
        '#title' => t('Name'),
        '#required' => TRUE,
        '#weight' => -5
        );
      $form['commentor_email'] = array(
        '#type' => 'textfield',
        '#title' => t('E-mail'),
        '#required' => TRUE,
        '#description' => t('The content of this field is kept private and will not be shown publicly.'),
        '#weight' => -3
      );
      break;
   }

Now how do I display the value of 'commentor_name' when previewing/viewing the comment?

Reply

Andy

Nevermind

Just found out that this *is* possible out of the box in Drupal 6, just not in a very intuitive or easy to find way.

You have to enable comment settings on a per content type basis. So, for blog posts you can enable user must enter contact information if posting anonymously.

Well, thanks for the tutorial anyways as now I know how to add fields to a form. If you still feel like answering my question above I'm still interested in how I would have done it.

Reply

Phillip Hershkowitz

Address fields?

Hi Addi,

Thanks for the article. I have two questions:

1- Can I add CCK fields to a webform? For example, cck_address.

2- My webform has 3 fields: city, state, zip. How do I get them to be on one line?

Thanks,
Phil

Reply

hyrcan

form alter to merge user-edit forms

From what I can see there's no way to call a sub-category of the user-edit form through the Forms API. (e.g. The category specified by the Profile.module) And as these categories are not their own form (no profile-edit-form) I can't see a way of pulling that specific section to merge it with the default "account" category form elements.

I can pull the elements in via direct calls to profile_form_profile() or user_edit($category), but this doesn't load in the $edit data it seems, nor does it save the data put into the merged fields.

Do any of you know how to pull the 'full' user-edit form (including all categories)?

Reply

Anonymous

Needed this

I also want to know how to do this, but as I read through drupal docs, this has been a long issue. I would really like to see how to merge two or more user edit categories coz I might be needing this for one of my projects. form_alter I guess will not be of use for this at the moment.

Reply

Anonymous

Great overview!

The Form API is a pretty darn powerful way to change how Drupal functions...Much of what we do after all is submitting forms, right? Content "management" system... Thanks for this post, it was VERY helpful. The API was lacking a little documentation and the overall form api is designed extremely poorly. It's far too much code to do what it does and it can throw people off to begin with. It doesn't save any time, a brand new form could be created (with validation) faster...But if you're looking to remain compatible, you're stuck. This article is a life saver.

I guess we just need to understand it's all carried forward from old Drupal code and we are dealing with some severe functionality...Upgrades would start to become difficult if it was overhauled too much. Definitely make sure you're looking at the right documentation for your version of Drupal! I noticed some minor changes that threw me off until I realized my search brought me to information for an older Drupal version.

Reply

antipix

^^

one of best sources to get drupal tips !
Thanks ^^

Reply

Don

Drupal Advance Search

Hi,

In drupal advance search you can see all the (taxonomy ) vocabulary and terms in a single selection box. Is there any way to split up according to the vocabulary as like the vocabulary shown in create content area.

with regards,
DOn

Reply

DrupalFan

Title Weight

Hi, Thanks for the article. I tried to change the weight of the title without success. Please tell me where I am wrong. I am using Drupal 5.x

I have a CCK content type with 8 fields. The title should go the bottom. I can alter all the weight except Title and Body in CCK. By default title weight is set to -5 and I want to change it into 10. The form id is myspecial_node_from

So, I created a module and activated it. This is the code for newform.module:

?php
function modulename_form_alter($form_id, &$form) {
  switch ($form_id) {
    case 'myspecial_node_form':
    $form['title']['#weight'] = 10;
      break;
  }
}
?>

Thanks.

Reply

DrupalFan

It works

I misunderstood the comment - The name will always be modulename_form_alter.

Now it works. Thanks.

Reply

theamoeba

thanks a lot

hi, thanks for this article. it was really useful. been looking for summin like this for days.

Reply

kmitz

cck and form_alter

Hi,

I wanted to construct a link from a cck content type of 'contact' (name, address, etc) which would go to another cck content type 'activity'. The url will be 'node/add/activity/10', which is the standard url with the contact's node id appended. I want the activity to be a partially pre-filled form (fill in an autocomplete text field + several address fields) based on the '10' (contact's node id).

I've managed to get the node reference autocomplete field to fill in using form_alter with:

//this works
$form['field_customer_name'][0]['#default_value'] = array('nid' => arg(3));

where arg(3) would be '10' in this case.

but the other cck fields don't want to accept a #default_value (this is the array 'path' I found by the technique mentioned above):

//none of these work
$form['field_addr1'][0]['#default_value']['value'] = '325 State Street';

I also tried several other iterations, including :
$form['field_addr1'][0]['#default_value'] = '325 State Street';
$form['field_addr1']['#default_value'] = '325 State Street';

The last one gets the text into the bottom of the fieldset, but not where it's supposed to be...what am I missing?

Reply

kmitz

reply to self...

I found this by webchick (Angie Byron): http://drupal.org/node/144132#pre-render

So I put this in my form_alter:

$form['#pre_render'] = array('assign_default_values');

I then created a function called assign_default_values which did a query and attempted to assign default_values like this:

$form['field_addr1']['#default_value'] = $_result->addr1;
...
return $form

BTW, I kept getting an 'unsupported operand types' error complete with a WSOD. When I read a little further down the page, I found that in D6, you must return the $form variable as it is not passed by reference.

Unfortunately, the default values are still not getting assigned. The query is successful and the result is populated (I'm able to print_r the result). I've also tried to assign the query result values to the array path I described in the above post. No luck.

???

Reply

kmitz

did it with jQuery

As I'm kind of pressed for time, I decided to go the AJAX route.

Probably what I should have done all along...

Cheers!

Reply

Jared

How About Some Asterisks In The Password Field?

Fantastic article! You really made it all make sense for someone new to all this Drupal craziness.

I'm using this approach to modify the default user_login_block. I have no trouble putting a generic placeholder in for the user name:

<?php
$form
['name']['#value'] = t('name');
?>

But I'd like some asterisks or something to be in the password spot, too, but this doesn't seem to do the trick:

<?php
$form
['pass']['#value'] = t('****');
?>

Any idea how to get it to let me put something there?

Thanks!

Reply

Wolfie

My vars won't show up :(

Hi,
I've got Drupal 6.x running and followed the article.
When I try to print out the array with return print_r($form); nothing happens ... so obviously I also can 't change anything in the Edit User page.

Any ideas (I already cleared my cache after changes , so that's not it)

Reply

Anonymous

why can't somebody

just tell me how to create an entirely custom form?

Seriously html forms are pretty staple and take 30 seconds to knock up.

All I want is a simple custom form with the action of my choice on it, is that so hard really? really?

Reply

Anonymous

Put elements on the same line?

Drupal always put one field at a line by default.
I want to display a text field with some description before it and also after it (on the same line), how to achieve it easily?

e.g.
Your weight + text field + kg

Thanks for any suggestion.

Reply

gary viray

drupal is fascinating

I ran out with all the solutions I know to tweak my drupal apps into something more visually enhancing site but then, I gave up. Good thing, I found your site today and men! you solved it!

Thanks.. - Busby SEO Test

Reply

Justin

Array Won't Print Legibly

First off, thanks for the excellent tutorial. My only problem is that my arrays print out all in one continuous line. I can't figure out the hierarchy, so I can't then figure out how to theme specific form elements. I'm using print_r and var_dump in my theme override function in template.php, but both do the same thing. I also have the Devel module installed, but when I replace print_r or var_dump with dsm, nothing happens (no array output at all on the form pages). Thanks very much for any help.

---

Here's a sample excerpt of what my array print_r outputs:

Array ( [#method] => post [#parents] => Array ( ) [#tree] => [#required] => [#action] => /user/login [#validate] => Array ( [logintoboggan_user_login_validate] => Array ( ) [user_login_validate] => Array ( ) ) [#theme] => user_login [#processed] => [#submit] => Array ( [uc_cart_user_login_form_submit] => Array ( ) [user_login_submit] => Array ( ) ) [#attributes] => Array ( ) [#description] => [#type] => markup [#parameters] => Array ( [0] => user_login ) [name] => Array ( [#type] => textfield [#title] => Username or e-mail address [#size] => 60 [#maxlength] => 60 [#required] => 1 [#attributes] => Array ( [tabindex] => 1 ) [#description] => You may login with either your assigned username or your e-mail address
Reply

addi

You can try two things

You can try two things here:
1. Put HTML <pre> tags around the print_r, for example:
$output .= '<pre>'. print_r($form) .'</pre>';

2. View source from your browser.

I'm not sure why a devel dsm isn't working for you. If it is enabled that function should be available.

Reply

Justin

thanks!

View source worked like a charm, but tags had the same result. Thanks again for all of your invaluable help! Saved me from awful frustration.

Reply

Horacio Salazar

Username never gets sent when unsetting its array

Addi:

An unexpected consequence of using the first method to hide parts of the form is the fact that the author field, which ordinarily gets automatically filled with the username, stays empty, thus sending the form with the field empty and making 'Anonymous' the content's author. Is there a way to insert the value without reinstating visually the field? Thanks for such a nice write up (it's been on my bookmarks since I first read it!).

Cheers from México.

Reply

orangecoat-ciallella

Hiding or unsetting form fields without losing the values

Horacio,
If a form field is unset() or not displayed on the screen through drupal_render(), then the default values aren't passed to the submit function. As you found, some values like Title, Published, and Author will either fail validation or will save no value to the database.

This helps protect against cross-site forgery because, according to the D6 FAPI documentation,

Faking a POST is much harder since it won't let values that weren't actually on the form come through to the $form_state['values'] in your submit function

In Drupal 5 it was possible, at least in my experience, to unset() form fields or just call drupal_render() on only a subset of form fields and still successfully submit without losing all the unrendered form values. However, this may not have been the most appropriate method.

The Form API in both Drupal 5 and 6 explain setting ['#access '] = FALSE on any form fields you don't want to be "accessible".

IMPORTANT: Setting #access property should be done within a form_alter() hook. The reason being, in Drupal 6 if hook_theme() is used to register a custom theming function or template (.tpl) for the form then using #access = FALSE will only cause the target form element will disappear. Since the $form variable isn't passed by reference to the theme layer the form processing magic doesn't see the #access change you made and you'll continue getting validation errors or empty values saved to the database.

For example, to remove the author name input field from the form but still maintain the field's previous value after a submit you can use the following inside of a form_alter() hook.

$form['author']['name']['#access'] = FALSE;

Most form elements, and even fieldsets, have an #access property you can toggle to FALSE. Use something like print_r($form); to see which use #access.

Of course, you can still modify/override form values within a form_alter() hook as Addi described. If you want to modify a form field's value and hide it too there are two approaches.

1) Override the #value attribute and use #access to hide it.

$form['author']['name']['#value'] = 'someusername';
$form['author']['name']['#access'] = FALSE;

OR

2) Override the #value and change the form field's #type to 'value', which effective acts like an <input type='hidden'> form element, but without sending anything to the browser.

$form['author']['name']['#value'] = 'someusername';
$form['author']['name']['#type'] = 'value';

You can also use this '#type' = 'value' to pass any data you want over to your form's custom validate() or submit() functions. As the the D6 FAPI documentation points out,

$form['foo'] = array('#type' => 'value', '#value' => 'bar')

This is accessed in $form_state['values']['foo'], with a value of bar. This method is preferred because the values are not sent to the browser.

Reply

gmat

what a great post

I ran out with all the solutions I know to tweak my drupal apps into something more visually enhancing site but then, I gave up. Good thing, I found your site today and men! you solved it!

Reply

div

thank you!

thank you!!
your instructions and insight have allowed me to create a unique reg form that is exactly how designer thought it would be. thanks!

my next task is to create a block (on home page only) that will allow user to post into one of the 3 forums we have on the site. i am trying to avoid customizing the normal forum add forms (/node/add/forum) and build a custom entry form in this block.

i've added this to mytheme_theme function in template.php

     'forum_node_form' => array(
       'arguments' => array('form' => NULL),
       'template' => 'block-block-8',
     ),

and in block-block-8.tpl.php

print "HELLO";
drupal_render($form);

on the main forum entry screen (/node/add/forum) i see the form and HELLO. In my block, I am only seeing HELLO. so this tells me that the above is really only for the main entry page, and not targeting the block as i need it to.

some research i've done (forms API docs) tells me that b/c this is adding a node it differs from the normal form entry, a la user-register. that info tells me that i need some additional $node information in the tpl file, but this part is over my head at this point.

ie, drupal_get_form('user_register); displays the register form in that block...but

drupal_get_form('forum_node_form'), gives me the following error

ie, warning: Missing argument 2 for node_form() in /Users/john/Documents/HTMLDOCS/domain_com/modules/node/node.pages.inc on line 93.

and then displays the the Revision, Authoring and Publishing Links, and Submit/Preview links. anonymous users only see the Submit/Preview links.

maybe the $user info is not available so the form can't be completely drawn? not sure.

any help or pointers would be greatly appreciated!

thanks!
div

Reply

yann

oh yeah

very nice tuto, god bless you.

Reply

Anonymous

I can alter a field title, but CAN'T alter the form redirect?

I want to get rid of the redirect to the homepage after submission of the default site-wide contact form. I'm puzzled as to why this isn't working:

<?php
function mytheme_theme(&$existing, $type, $theme, $path) {
// we're based on zen
$hooks = zen_theme($existing, $type, $theme, $path);

// add a hook for the site-wide contact form
$hooks['contact_mail_page'] = array(
'contact_mail_page' => array(
'arguments' => array('form' => NULL)
)
);

return $hooks;
}

function mytheme_contact_mail_page($form) {
// override the "category" label in the site-wide contact form
// OK, this works
$form['cid']['#title'] = t('Send to');

// override the form redirect - return to contact page
// this one doesn't work - no other valid path works either
$form['#redirect'] = array('contact');
return drupal_render($form);
}

Any insight would be appreciated, thanks

Reply

Manuel Garcia

How to print the user profile form in d6?

I've been struggling these past two days trying to print the user profile form on a custom node, however I cannot seem to get it right.

I have tried printing drupal_edit_form:

<?php
// THIS kinda works, but no submit button
global $user;
$uid = $user->uid;
foreach (
$user as $key => $value) {
 
$account[$key] = $value;
}
print(
drupal_get_form('user_edit_form', $uid, $account));
?>

Invoking the user module:

<?php

// no success either
global $user;
print
module_invoke('user', 'form', $user, 'account'));
?>

Trying to print user_profile_form also returns an empty form... I'm kind of puzzled by this problem, has any one gotten this to work? I imagine this must be possible...

Great write up btw, theming forms is always a good exercise !

Reply

Tom Tom

Thanks

I ran out with all the solutions I know to tweak my drupal apps into something more visually enhancing site but then, I gave up. Good thing, I found your site today and men! you solved it!

Reply

Delkin

Thanks for the nice

Thanks for the nice tutorial. I've added a couple custom fields to my comment form. Much like this very comment form I'm filling out now: "Name" with a title of 'commentor_name' and "E-mail" with a title of 'commentor_email'. This works fine and the fields show up when filling in the comment.

Reply

Chris

Maybe I am not getting

Maybe I am not getting something. I am trying to do this with a custom content type. I followed this to the t and am not getting drupal to call the function(yes i cleared cache). Does this only work with core modules or shouldnt it work with all forms?

Reply

scott

Close form

Great article and enjoy your site. I was able to modify the form to way I like thanks to your article. I am now just trying to find a way to close the form after the user submits or save the entry. Not sure where to start with this.

Reply

jammer

great post

Never mind. Installed the contact_redirect module and patched it for Drupal 6...

Reply

Anonymous

Form_alter doesnot work for me Any Clues ??? (Using DRUPAL 6)

I am using drupal 6

I created a new module name customizedlogin i want to append extra characted to username field after the user has submiited .
i am trying to do as following

function customizedlogin_form_alter(&$form, $form_state, $form_id){

form_set_value($form['name'], $replacement_value);
}

i am not getting wot is expected

printing of $form is giving me an empty array print_r ($form).Any Clues ?

Reply

James

Great Article

Gave me an excellent quick overview and has pointed me in the direction I was looking for.

Reply

Glenn

Modify node, not form

Hi

How do I modify the node view, not the node edit?

I can't find a hook_node_alter or anything like this. I want to use a module to add some content to a particular content type's node view.

How can I do this?

Thanks

Glenn

Reply

redbeard

Nothing I attempt to update seems to have any effect

I'm using a CCK generated form but I want to add word before and after a text field.

when I do some thing like:

<?php
/**
   * Theme override for marathon_entry form.
   *
   * The function is named themename_formid.
   */
 
function a3_atlantis_marathon_entry_node_form($form) {
   
dsm($form);
   
$form['title']['#field_prefix'] = t('Hello');
  }
?>

Nothing happens.
Even when I do:

<?php
/**
   * Theme override for marathon_entry form.
   *
   * The function is named themename_formid.
   */
 
function a3_atlantis_marathon_entry_node_form($form) {
   
dsm($form);
   
$form['title']['#title'] = t('Hello');
  }
?>

The Title stays the same.

any ideas?

Reply

dellis

Thanks for your help

Hey, fantastic stuff. This really helped me figure out drupal forms! I'm still learning, but by mainly combining #prefix and #suffix and a little bit of jquery (I'm still learning) I've managed to get "most" of what I need. Thank you very much for all of the effort that you guys put into educating the rest of us--it really does help.

so far: http://www.vimeo.com/4169918

Reply

Rosamunda

About themeing the edit form: what if I want to take it over?

Hi Addi!
This article is very easy to follow! Thanks!!
There is one question that pops up when I try to follow it: What if I want to add a certain message for only certain roles, in the edit (and NOT the node/add) page?
I´ve tried

function mythemename_theme() {
  return array(
    'my-cck-nodetype_node_form' => array(
    'template' => 'my-cck-nodetype-node-edit',
    'arguments' => array('form' => NULL),
    ),

  );
}

and this (on the template file)
    function mytheme_my-cck-nodetype_node_form($form) {
$output .= drupal_render($form);
return $output;
  }

But there is no way that the my-cck-nodetype-node-edit.tpl.php file would show up the rendered form.
I´ve tried print $output with no luck.
And i just want to code inside the tpl file a different stuff for each different role.
So, that way, I could completely remove the edit form for role X.

Thanks for your time and your input!

Rosamunda

Reply

theoldfather

Drupal 5: force drupal to not re-sort your elements!

I had a giant list of elements in my form which I needed to reorder. I selected them from the original $form array and reordered them and fed the array back into drupal_render();

At this point, drupal was re-sorting my elements even though they were ordered correctly in the array.

YOU MUST set $form['#sorted']=true or drupal_render() will attempt to re-order your elements for you.

Took me far too long to figure this out and thought I would pass it along. Hopefully someone else will not spend hours in frustration like I did.

Reply

Rosamunda

Thanks for the tip

Thanks for the tip theoldfather.
Sorry for this php-newbie question... how do I set that $form['#sorted']=true line of code? inside the template file I guess, and it should be like

function mytheme_preprocess_myccknode_node_form(&$vars) {
$vars['myccknode_render'] = drupal_render($vars['form']);
$form['#sorted']=true;
}

I´ve tried that already, and so far, it didn´t changed where the submit and preview buttons where displayed.
Any thoughts?

Thanks!!!

Reply

Sylvain

I created a story type

I created a story type (ads), get form_id value (ads_node_form)
I try to include the payment form of a payment module inside the module

the button of payment is opening a popup and if I put my code, the module payment make same action than the form button :(

here the code

function garland_ads_node_form($form) {
      $output ='';
      $output .= mymodule_subscriptions();
      $formulaire = drupal_render($form);
      $output .= $formulaire;
      return $output;
}

what is the good code to work correctly ? :-)

Reply

ian

changing page title

I've customized all my forms using this method but I can't change the 'Create [node type]' title of the page. Does anyone know how to change the title of the form by content type?

Thanks for all the great tips

Reply

jerome

Default value for body textarea

Hello,
Thank you very much for this useful article.
by following your example, I try to set up a default value for the Body textarea, but it is never display in the node form.
Function registration in my homemade theme:

function homemade_theme() {
   return array(
     // The form ID.
     'article_node_form' => array(
       // Forms always take the form argument.
       'arguments' => array('form' => NULL)
     )
   );
}

Function to set the default value to body in the article creation form:
function homemade_article_node_form($form) {
$output = '';
$form['body_field']['body']['#title']="test";
$form['body_field']['body']['#default_value']= "test";
$output .= drupal_render($form);
return $output;
}

I don't understand why the body title is correctly changed but not the textarea body field.

Please help me to understand my error.
Jerome

Reply

Tars

Change Button Type

Can you use this override to change the button type to image? I tried using:

$form['submit']['#type'] = image;
$form['submit']['#src'] = /images/blue-arrow.gif;

On the search block form but that just made the submit button disappear all together.

Thanks!

Reply

Anonymous

I hope this get answered

Firstly, i agree with the hundreds of post, it was a clear and concised, well written tut.

I have a question about different form themes in the same site.

At the moment i am customising the user_rego page and i find that obviously when i edit the form all instances of the form change.

Can this be done?
Can anyone explain how?

Ilan

Reply

Elandirayan

Some more clarifications.

Hai one and all,

This is elan. I am Having some doubt regard the Hook overriding. I Implemented as per the turorial. But my query is if suppose i want to add any new field with this user block ( let's assume an age) what i have to do. and where i have to add.

I hope a soon reply from you friends.

Thanks & Regards

Elandirayan.J

Reply

Steve

How do you know if a

Great tutorial, but I have one big question.

Under D6 theme override you say:

For forms that do not have templates or registered functions though, we need to not only create the override function but we also need to register it with the theme system so it knows about it.

But you don't explain how you know whether or not the form has a template or a registered function already. Where does one find that information?

Thanks for your help in advance!
Steve

Reply

addictingames

Useful Tutorial

Thank you so much for this tutorial, my friend are about to learn Drupal and he really need this.. I will give this link to him.. Great post ^^ and nice to know you...

Reply

How To Grow Taller

it really does help.

This really helped me figure out drupal forms! I'm still learning, but by mainly combining #prefix and #suffix and a little bit of jquery (I'm still learning) I've managed to get "most" of what I need.

Reply

deeper voice

I am Having some doubt

I am Having some doubt regard the Hook overriding. I Implemented as per the turorial. But my query is if suppose i want to add any new field with this user block ( let's assume an age) what i have to do. and where i have to add.

Reply

Sean

Location Display Settings Weight

I'm trying to alter the weight options in the Display Settings of the Location fieldset.

$form['location_settings']['display']['weight']['#options'] = arrray(-20,-19,-18...);

The Default is not "light" enough. I think this should work based on what I know about form alter, but it doesn't. Is there something about overriding weight options with the hook_form_alter that I'm missing?

Thanks!
Sean

Reply

grow taller

hat i have to do.

This is elan. I am Having some doubt regard the Hook overriding. I Implemented as per the turorial. But my query is if suppose i want to add any new field with this user block ( let's assume an age) what i have to do. and where i have to add.

Reply

Malware Removal Bot

errore

When I try to print out the array with return print_r($form); nothing happens ... so obviously I also can 't change anything in the Edit User page.

Reply

Anonymous

printing $form

If you are not getting any input, it is probably there is no form in that page. Or sometimes you don't see the print output on a page, you can either check in firebug or in generated view source. I hope this helps.

-Gowri

Reply

Ways To Get Ex Back

Ways To Get Ex Back

I've customized all my forms using this method but I can't change the 'Create [node type]' title of the page. Does anyone know how to change the title of the form by content type?

Thanks for all the great tips

Reply

Anonymous

Hi there, Thanks for the

Hi there,
Thanks for the tutorial.
Please could you let me know how to display the form array data from the return print_r($form) function, as you have (nice and pretty!)
When I print my data it comes up as constant strings of code which are virtually impossible to disipher.
I would like to change the size of the body field on a node edit form - but can't find the array data.
Thanks

Reply

Danny_Joris

I'm calling the right page, but it's not working.

I build a little module and added this:

<?php
// $Id$

/**
* @file
* Module to hold my customations to No English in Front End.
*/

/**
* Implementation of hook_form_alter()
*/
function noenglish_form_alter(&$form, $form_state, $form_id) {
  if (
$form_id == 'page_node_form') {
    
    unset(
$form['language']['#options']['en']);
    return
print_r($form);
  }
}
?>

I am calling the right page/form because it calls the print_r($form) list.
The funny thing is that it takes away [en] => English in the list generated with return print_r($form); ,but the 'English' option was still there in the dropdown! I don't understand that.

Same if I use your "unset($form['comment_settings']);" example...

Any suggestions are very welcome.
Cheers,
Danny

Reply

Anonymous

$vars in _form

Hello,

I cannot get one thing - in theme_preprocess_node i get all kinds of useful variables ($vars in zen) AND in theme_form i get to alter form elements. Problem is that i want to alter form WITH variables but i dont know how. I want to insert NID as default value of node_edit form node reference cck field. I cannot get NID from URL because node is displayed as full node in view result.

Looking for answers. Thanks.

Reply

Anonymous

Hey - thanks for the

Hey - thanks for the tutorial.
I want to edit a node form using the module method.
Any ideas as to why the following isn't overriding my form:

<?php
// $Id: customsite.module

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


  
* Implementation of hook_form_alter().
   *
   *
The function is named node_edit_form_alter.
   */
  function
node_edit_form_alter(&$form, $form_state, $form_id) {
   
// Normally a switch is used because you may want to alter more than
    // one form and it is easy to add a new case for each form.
   
switch ($form_id) {
     
// This is our form ID.
     
case 'node_form':
       
$form ['body_field']['body']['#rows'] = 4;
        break;
  }
?>
Reply

Majdi

Hello I used the theme

Hello
I used the theme method with Drupal 6 , it did not work , I got error says

call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'Golden_user_login_block' was given in C:\xampp\htdocs\golden\includes\theme.inc on line 617.

but with modules method its work fine ... why ?

Thanks for help

Reply

Sydney Monis

Thanks a Lot

Thanks a ton. I've been searching for this particular stuff for two of my sites running on Drupal, after a troublesome search for 2+ hrs i finally seem to have reached somewhere. Will try it out :)
Regards Sydney from SEO Articles.

Reply

Anonymous

I've used this and it works great

Hi there, I'm a Drupal developer and I've used this method on a couple of the sites of worked on recently and it works great. Just wanted to say thanks and to let everybody else to learn this technique, it's an important part of learning Drupal.

Thanks

Reply

Nancy Rackleff

How to access buttons on filefield widget

I have the variables printing out to the page, but the item I want to access doesn't seem to be available to override this way. I want to change the text on the "upload" button of a cck filefield widget to says "Attach" instead of upload, but only on this one form. All I see for this form variable is
#type (String, 16 characters ) filefield_widget | (Callback) filefield_widget(); It lists a few other items, but not the button text. Does anyone know how to access that on just one form.

Reply

Albert

Changing the action attribute

Hi Addi,

I want to change the 'action' attribute of user login form (yes, the login form will be used for another backend system). And I already put this code in template.php:

function myowntheme_theme() {
  return array(
    'user_login_block' => array(
      'arguments' => array('form' => NULL),
    ),
  );
}

function myowntheme_user_login_block($form) {
  $output = '';
  $form['#action'] = 'http://www.blablabla.com/authentication/doLogin';
  $output .= drupal_render($form);
  return $output;
}

But it failed to alter the 'action'. The form still send its contents to default target. What did I do wrong in the code? I have tried to print_r the content of the $form var, and it already gets a new value for 'action'.

Thanks in advance.

Reply

Albert

Changing the action attribute

Hi Addi,

I want to change the 'action' attribute of user login form (yes, the login form will be used for another backend system). And I already put this code in template.php:

function myowntheme_theme() {
  return array(
    'user_login_block' => array(
      'arguments' => array('form' => NULL),
    ),
  );
}

function myowntheme_user_login_block($form) {
  $output = '';
  $form['#action'] = 'http://www.blablabla.com/authentication/doLogin';
  $output .= drupal_render($form);
  return $output;
}

But it failed to alter the 'action'. The form still send its contents to default target. What did I do wrong in the code? I have tried to print_r the content of the $form var, and it already gets a new value for 'action'.

Thanks in advance.

Reply

Deepak

Exposed filter

Hi,

I am trying to modify the form (exposed filter). It has two select boxes and i want the second select box to be loaded based on the one selected in first. The two select boxes are Country and and City. Please tell me if it can be achieved? or if there is any other way to achieve this.

Thank you

Reply

cerita dewasa

GREAT

Nice info, Useful for my job...this has made my life (my projects) goes a lot easier. Keep up the good work, thanks very much... :)

Reply

cewek bugil

THANKS

I came across your site while searching on MSN and have now added you to my rss reader. I Just though i should say “keep up the good work” and pass on congratulations on a job well done ! I am really looking forward to seeing more from you in the future.

Reply