MYTHEME_form_element_FORMID? I have an override for my theme called:

corporate_form_element()

The base hook was copied and tweaked. Multiple forms have to be modified and in some cases some individual elements did too. I typically get around this by checking conditionally whether markup is needed.

For instance I check for checkboxes and theme accordingly:

&lt;?php
if($element['#type'] == 'checkbox'){
    return '&lt;div style="width: 30%; float: left"&gt;' . $output . '&lt;/div&gt;';  
}  
?&gt;


However now I wish to theme two text fields quite differently than most others in forms and I have discovered there is no way to detect which form the current call is for. I have "hacked" this by adding custom '#fields' in my forms elements (either those I provided explicitly or hooked into via hook_form_alter) and checking for this.

This works but is a horrible hack and not very clear.

What is the preferfed drupal way of achiving this result? Can I overrivde MYTHEME_form_element_FORM_ID or something similar? I know this can be done to MYTHEME_form_alter but what about individual elements????

Alex
Using custom properties is not an hack; quite the opposite, it is a perfectly fine way to achieve what you want. It allows you to identify the form elements that need to be altered, which is what you want.

In fact, custom properties are normally used from Drupal, which uses the following code for fields associated to an entity.

  $element = array(
    '#entity' =&gt; $entity,
    '#entity_type' =&gt; $instance['entity_type'],
    '#bundle' =&gt; $instance['bundle'],
    '#field_name' =&gt; $field_name,
    '#language' =&gt; $langcode,
    '#field_parents' =&gt; $parents,
    '#columns' =&gt; array_keys($field['columns']),
    '#title' =&gt; check_plain($instance['label']),
    '#description' =&gt; field_filter_xss($instance['description']),
    // Only the first widget should be required.
    '#required' =&gt; $delta == 0 &amp;&amp; $instance['required'],
    '#delta' =&gt; $delta,
  );


Custom properties are also the Drupal 7 way to pass variables to theme functions. For example, the following code is using theme_table() to render part of a page.

  $build['node_table'] = array(
    '#theme' =&gt; 'table',
    '#header' =&gt; $header,
    '#rows' =&gt; $rows,
    '#empty' =&gt; t('No content types available. &lt;a href="@link"&gt;Add content type&lt;/a&gt;.', array('@link' =&gt; url('admin/structure/types/add'))),
  );


Passing $build to drupal_render() produces the same output produced by the following code.

$html = theme('table', array('header' =&gt; $header, 'rows' =&gt; $rows, 'empty' =&gt; t('No content types available. &lt;a href="@link"&gt;Add content type&lt;/a&gt;.', array('@link' =&gt; url('admin/structure/types/add')))));


The alternative would be adding a #after_build or #process function to the form elements, but those functions are called before the form element is rendered, which means they can just alter the form element properties.

Those functions get access to the content of $form_state, and get $form_state['input']['form_id'] or $form_state['input']['form_build_id']. This is what the documentation for drupal_build_form() says about $form_state['complete form']:


  A reference to the $form variable containing the complete form structure. #process, #after_build, #element_validate, and other handlers being invoked on a form element may use this reference to access other information in the form the element is contained in.


To add a #after_build function (which gets $element and &amp;$form_state as parameters), you should implement hook_element_info_alter() to change the form element definition.

Notice that theme_form_element() is defined as theme wrapper for every form element, similarly to what done with the following code for the textfield form elements.

  $types['textfield'] = array(
    '#input' =&gt; TRUE,
    '#size' =&gt; 60,
    '#maxlength' =&gt; 128,
    '#autocomplete_path' =&gt; FALSE,
    '#process' =&gt; array('ajax_process_form'),
    '#theme' =&gt; 'textfield',
    '#theme_wrappers' =&gt; array('form_element'),
  );


As side note, every theme function has its own preprocess functions; for example, for theme_textfield() those functions are hook_preprocess_textfield(). They can suggest a different theme function to be used by adding values to the $variables['theme_hook_suggestions'] array. ($variables is the parameter passed as reference to the theme preprocess functions.) Unfortunately, the theme and the theme preprocess functions don't get any reference to the form being build.

References


drupal_build_form()
form_builder()
system_element_info()
theme()