function theme_field

You are here

7 field.module theme_field($variables)

Returns HTML for a field.

This is the default theme implementation to display the value of a field. Theme developers who are comfortable with overriding theme functions may do so in order to customize this markup. This function can be overridden with varying levels of specificity. For example, for a field named 'body' displayed on the 'article' content type, any of the following functions will override this default implementation. The first of these functions that exists is used:

  • THEMENAME_field__body__article()
  • THEMENAME_field__article()
  • THEMENAME_field__body()
  • THEMENAME_field()

Theme developers who prefer to customize templates instead of overriding functions may copy the "field.tpl.php" from the "modules/field/theme" folder of the Drupal installation to somewhere within the theme's folder and customize it, just like customizing other Drupal templates such as page.tpl.php or node.tpl.php. However, it takes longer for the server to process templates than to call a function, so for websites with many fields displayed on a page, this can result in a noticeable slowdown of the website. For these websites, developers are discouraged from placing a field.tpl.php file into the theme's folder, but may customize templates for specific fields. For example, for a field named 'body' displayed on the 'article' content type, any of the following templates will override this default implementation. The first of these templates that exists is used:

  • field--body--article.tpl.php
  • field--article.tpl.php
  • field--body.tpl.php
  • field.tpl.php

So, if the body field on the article content type needs customization, a field--body--article.tpl.php file can be added within the theme's folder. Because it's a template, it will result in slightly more time needed to display that field, but it will not impact other fields, and therefore, is unlikely to cause a noticeable change in website performance. A very rough guideline is that if a page is being displayed with more than 100 fields and they are all themed with a template instead of a function, it can add up to 5% to the time it takes to display that page. This is a guideline only and the exact performance impact depends on the server configuration and the details of the website.

Parameters

$variables: An associative array containing:

  • label_hidden: A boolean indicating to show or hide the field label.
  • title_attributes: A string containing the attributes for the title.
  • label: The label for the field.
  • content_attributes: A string containing the attributes for the content's div.
  • items: An array of field items.
  • item_attributes: An array of attributes for each item.
  • classes: A string containing the classes for the wrapping div.
  • attributes: A string containing the attributes for the wrapping div.

See also

template_preprocess_field()

template_process_field()

field.tpl.php

Related topics

File

modules/field/field.module, line 1161
Attach custom data fields to Drupal entities.

Code

function theme_field($variables) {
  $output = '';

  // Render the label, if it's not hidden.
  if (!$variables['label_hidden']) {
    $output .= '<div class="field-label"' . $variables['title_attributes'] . '>' . $variables['label'] . ':&nbsp;</div>';
  }

  // Render the items.
  $output .= '<div class="field-items"' . $variables['content_attributes'] . '>';
  foreach ($variables['items'] as $delta => $item) {
    $classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
    $output .= '<div class="' . $classes . '"' . $variables['item_attributes'][$delta] . '>' . drupal_render($item) . '</div>';
  }
  $output .= '</div>';

  // Render the top-level DIV.
  $output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';

  return $output;
}

Comments

Here is an example of the template file naming convention using a 'surname' field for an 'enquiry' content type:

field--field_surname--enquiry.tpl.php
field--field_surname.tpl.php
field.tpl.php

If you save a template without the 'field_' prefix (eg. field--surname.tpl.php), the template engine won't detect it. I don't think this is entirely clear in the 'body' example given above. Having read above, however, I'm now more inclined to make changes to my template.php file instead.

If you are displaying fields through a box/block and the fields are empty, the box/block still will show up. To avoid this:

<?php
function theme_field($variables) {
 
$output = '';

 

// Render the label, if it's not hidden.
 
if (!$variables['label_hidden']) {
   
$output .= '<div class="field-label"' . $variables['title_attributes'] . '>' . $variables['label'] . ':&nbsp;</div>';
  }

 

// Render the items.

/**** new var to check later for empty field values ********/
 

$is_empty = '';

 

$output .= '<div class="field-items"' . $variables['content_attributes'] . '>';
  foreach (
$variables['items'] as $delta => $item) {
   
$classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
   
/* ****  */
   
$rendered_item = drupal_render($item);
   
$is_empty .= $rendered_item;
   
/* ***** */
   
$output .= '<div class="' . $classes . '"' . $variables['item_attributes'][$delta] . '>' . $rendered_item . '</div>';
  }
 
$output .= '</div>';

 

// Render the top-level DIV.
 
$output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';
/*  ******* */
 
if (strlen(trim($is_empty))==0){ // maybe better checks are possible
    // all for nothing, but at least, we will not end up with rendered empty boxes
   
$output=FALSE;
  }
/*  ******* */
 
return $output;
}
?>

excellent and thank you. i still wonder where and why empty fields got printed, but they did. thanks!

Is there any reason why there should be a colon after the label?

I asked myself the same question. But, the good thing is that you can override the theme function with your own which does not include a colon.

I believe it's there in case the label is set to inline in the manage field display tab. IMO it's unnecessary now. We can add it with a css :after element if needed.

as for the function name suggestions;

  • THEMENAME_field__body__article()
  • THEMENAME_field__article()
  • THEMENAME_field__body()
  • THEMENAME_field()

do not forget to include the field_ prefix in the name.

If you have a field_author field in article content type, the overriding function names would be:

  • THEMENAME_field__field_author__article()
  • THEMENAME_field__article()
  • THEMENAME_field__field_author()
  • THEMENAME_field()

All you n00bs out there like myself, remember - you have to clear site cache in order changes to take effect. Hope it helped.

The default method above is full of divs, making it hard to visually lay stuff out. You can make this tag a variable that *defaults* to div instead, like so:

<?php
function MYTHEME_field($variables,$tag='div',$itemsep='') {
   
       
$isempty    = true;
       
$output     = '';
       
$sep        = '';
       
       
// Render the items.
       
$output = '<'.$tag.' class="field-items"' . $variables['content_attributes'] . '>';
        foreach (
$variables['items'] as $delta => $item) {
           
$classes    = 'field-item ' . ($delta % 2 ? 'odd' : 'even');
           
$rendered   = drupal_render($item);
           
$isempty    = $isempty && (strlen(trim($rendered))==0);
           
$output     .= '<'.$tag.' class="' . $classes . '"' . $variables['item_attributes'][$delta] . '>';
           
$output     .= $sep.$rendered;
           
$output     .= '</'.$tag.'>';
           
$sep        = $itemsep;
        }
       
$output .= '</'.$tag.'>';
       
        if (
$isempty) return '<!-- '.$variables['label'].': empty -->';
       
       
// Prepend the label, if it's not hidden.
       
if (!$variables['label_hidden']) {
           
$label  = '<'.$tag.' class="field-label"' . $variables['title_attributes'] . '>' . $variables['label'] . ':&nbsp;</'.$tag.'>';
           
$output = $label.$output;
        }
       
       
// Render the top-level DIV.
       
$output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';
       
        return
$output;
       
    }
?>

Then you can override *some* fields to use other tags instead, like so :

<?php
   
function MYTHEME_field__field_organisers($variables) {
        return
MYTHEME_field($variables,'span',', ');
    }
    function
MYTHEME_field__field_contributors($variables) {
        return
MYTHEME_field($variables,'b','/');
    }
?>

$2c,
*-pike

Thanks for posting the snippet pike67. Rather than adding additional options to your custom theme function as arguments, they should be added as key value pairs to the $variables array. Then accessed inside your function as $variables['tag'] and $variables['itemsep']

I'm not sure if the way you're doing it will actually break anything but passing it through $variables will allow those options to be set through render arrays and modified with preprocess and process functions.

I hope this helps.

Notice if you return '' from your themed field function, something somewhere may decide to call a different theming function to get its output from. I'm not sure if that's a bug and/or how exotic that bug is. Just return `< ! - - empty - - >` to signal the output is empty.

$2c,
*-pike