Drupal 6 provides many avenues to modify its appearance, including ways to theme a form. Recently I themed all node edit forms at once. I will share here how I did it.
The usual route to theme a node edit form, or any form for that matter, is to grab the form ID, which is used as a theme hook, and implement a hook_theme
function in template.php in the theme.
'blog_node_form' => array(
'arguments' => array('form' => NULL),
'template' => 'blog-node-form',
)
);
}
?>
This lets you alter the theme registry to add a template file for a specific form. There are many blog posts that go into more detail than I do here on how to theme forms in general.
The above is useful if I want to theme a blog content type or the user registration form, for example. Most sites have at least a few different content types. I wanted to make alterations to all node forms at once and use a single template file. This involved a slightly different approach.
Correction: This next step with the theme_registry_alter example is not necessary. See comments below this post.
There is a theme_node_form
theme function in Drupal, which is called by all node forms. I wanted to replace or supersede this theme function with a template. I tried to do this with hook_theme, but it continued to pick up some parts of theme_node_form
in addition to supporting my template file. So it called the form array twice, causing recursion; which is not what I expected. So instead I took a colleague's suggestion and altered the theme registry via hook_theme_registry_alter()
. This seemed clean and simple enough.
This takes the node_form
theme hook and changes it from a theme function to a template, in sites/all/themes/MYTHEME/template.php:
{C}function MYTHEME_theme_registry_alter(&$theme_registry) {
$theme_registry['node_form'] = array(
'template' => 'node-form',
'arguments' => array('form' => NULL)
);
}
?>
This worked great. But I hear that hook_theme_registry_alter
is intended for use in modules only? If you know why, please chime in with a comment. Or leave a comment on the theme registry for special cases handbook page.
And the fun part... Spiffing up the node edit form
Here is what I did. This creates two columns for the form and places all top level form fieldsets on the right.
Screenshot:
And here is how I did it...
{C}
Markup in the template sites/all/themes/MYTHEME/node-form.tpl.php:
{C}print $form; ?>
{C}print $buttons?>
{C}print $fieldsets; ?>
A little CSS for the columns:
.node-form-left {
float:left;
margin-right:2%;
width:640px;
}
.node-form-right {
float:left;
width:300px;
}
Peprocess function in sites/all/themes/MYTHEME/template.php:
{C}/**
* Preprocess for node-form.tpl.php
*/
function MYTHEME_preprocess_node_form(&$vars) {
foreach($vars['form'] as $key => $value) {
if (is_array($value) && $value['#type'] == 'fieldset') {
$vars['fieldsets'] .= drupal_render($vars['form'][$key]);
}
}
$vars['buttons'] = drupal_render($vars['form']['buttons']);
$vars['form'] = drupal_render($vars['form']);
}
?>
So what this does is create and prepare a few variables for my template. First it loops through the form array grabbing all fieldsets and puts them in $vars['fieldset'];
. I then print this variable in the template. Similarly, it creates a buttons variable that grabs the submit buttons. There are a lot of ways to view the array, but I usually use print_r($vars['form']);
in my preprocess function when I want to see what's happening behind the scenes.
As alternative route to do all this is with a theme overwrite function, which would look like this (I did not test this snippet!):
Update: See this comment for a version of this snippet that works.
/**
* Theme overwrite of theme_node_form();
* Note, this is UNTESTED CODE, but it should work.
*/
function MYTHEME_node_form($form) {
$output = '
';
$output .= drupal_render($form['buttons']);
$output .= drupal_render($form);
$output .= '
';
$output .= '
';
foreach($form as $key => $value) {
if (is_array($value) && $value['#type'] == 'fieldset') {
$output .= drupal_render($form[$key]);
}
}
$output .= '
';
return $output;
}
?>
So I could have used a theme overwrite instead of manually altering the theme registry. Theme functions are five times faster than using a template, so often it's recommended and preferable to use a theme function.
So there you go. That's how I themed all node edit forms with a template and preprocess function.