Theming Forms with Theme Functions
The decision of whether to use a theme function or a template file is a personal/team preference. If you’re comfortable using PHP, you might be inclined to use theme functions. If not, you’ll probably prefer a template file, which is explained in the next section.
As discussed above, you’ll need a
hook_theme() implementation, without a template or path index, as shown in Listing 16–28. After doing this,
HOOK_contact_site_form() is an official theme hook that can be overridden like any other theme function. Even though a
theme_contact_site_form() function doesn’t exist, you still name it as you would any other theme function override:
Using drupal_render_children() Is a Must!
drupal_render_children() takes care of rendering all of the children of the form. This function alone will result in the exact same code Drupal would have provided without your theme function, which makes the function in Listing 16–28 pretty useless by itself, but it’s worth stressing that it’s VERY important to always use
drupal_render_children($variables['form']) at the bottom of your function.
Even if you call
render() on every element you have added to the form, Drupal will have added some important hidden elements identifying the form and those need to be rendered, too. So calling
drupal_render_children($form) at the end of the theme function is mandatory. This won’t re-print
drupal_render() knows it has printed already. As an added bonus, it will take care of any additional elements added by other modules.
Manipulating Form Elements in Theme Functions
Now that we've gotten that out of the way, let’s make some changes to the markup. Just like any theme function, the code this function returns will be inserted directly into the page markup. Since forms are render elements you need to render them. The code in Listing 16–29, does the following:
- Changes the labels of the name and mail elements.
- Renders the name and mail elements individually.
- Arranges the markup and individually rendered elements in a variable called
$outputat the bottom of the theme function.
- Finally, it returns the
Forms and their contents are render elements, so you can use
render() functions to manipulate the elements of the form. When using
hide() or making changes to the form array inside the theme function, you’ll need to make sure you do so before attempting to render. There are a lot of other things that can be done here. We can’t possibly cover all of them, but here are a few quick examples of what can be done:
#weightproperty of an element to change the order in which they print. The following code would cause the message element to print at the top of the form:
- $variables['form']['message']['#weight'] = -10;
- $variables['form']['message']['#sorted'] = FALSE;
Add a description underneath an element by setting the element
#descriptionproperty, like so:
- $variables['form']['mail']['#description'] = t("We won't share your e-mail with anyone.");
Set the default value of form element, such as checking the "Send yourself a copy" checkbox, by default setting the
TRUE, like so:
- $variables['form']['copy']['#checked'] = TRUE;
#theme_wrappersproperty to remove the label and wrapper
<div>and re-create the markup exactly the way you want it, like so:
More advanced changes include making the form display in a table by using the
… and so on!