Customizing Drupal Forms: What I just learned
I've been working on a project that required some pretty heavy-duty customizations to how the user registration form looks and while getting everything to work I learned a few things that have changed the way I look at customizing forms in Drupal. Here is a quick summary of what I already new, and what I know now.
Altering forms
Ok, this part I knew already... It's pretty easy to change certain aspects of your form elements from within a module by using either hook_form_alter(&$form, &$form_state, $form_id)
or by using hook_form_FORM_ID_alter(&$form, &$form_state)
Here is a quick example of removing the title from a form element so that no <label> tag appears when the form renders:
function mymodule_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'the-form-I-want-to-alter') { $form['birthday']['#title'] = ''; } }
Theming forms
Here is one that I didn't know: every form already has a theme function pre-defined. For instance, if you want to change how the user registration form (form_id: 'user_register') is themed, then simply create a function in your theme's template.php called mytheme_user_register($form){ ... }. One important thing to remember though is that this function must return the rendered version of your form. Here is a simple example:
mytheme_user_register($form) { $output = ''; $output .= '
'; return $output; }
note: you still need to regster your mytheme_user_register function in hook_theme() and then clear your cache.
Rendering forms
My most interesting discovery was about the drupal_render function. If you use drupal_render to render individual elements within your theme function, then when you call drupal_render($form) it will only render the elements you haven't already rendered. (WOW "render" 5 times in one sentence!). For an example of what I mean, check out the theme_user_admin_perm function. Basically, the function is using drupal_render on each permission checkbox and adding that to a $row, which ultimately gets sent to theme('table'). Finally, the drupal_render($form) call renders the rest of the form - whatever is left - like the submit button.