A simple CCK formatter for on/off checkbox fields

September 26, 2011
blog author

Appno Blogger

Appnovation Coop

The behavior of Drupal cck's single on/off checkbox field is a little different than other cck fields. Normally, a field has a label above its input element (text field, select list, ...). With a single on/off checkbox the field label as entered when creating the field does not appear on the node edit form. Instead, the label associated with the 'ON' value will appear to the right of the checkbox. This is the intended behavior and when the label associated with the 'ON' value is descriptive, it is intuitive enough on the node edit form. However, some difficulties can arise when trying to accommodate both the node view (or views display) and the node edit form. Here is an example of a possible solution for one particular case.

 

The Problem

Suppose a field called 'Club Member' to record whether the node/person is a Club Member or not. I want to store the actual value as an integer, so I use an integer type field. I have to choose a field label as well as key|label pairs for the ON and OFF values. By default these will be displayed in this way: on the node page Field Label: Value Label and on the node edit page [] ON-Value Label So if I name my field 'Club Member' and use 0|NO and 1|YES as key|label pairs I get: on the node page Club Member: No and on the node edit page [] YES This obviously doesn't work on the node edit page because I have no idea what I'm saying YES to. So I try key|label pairs 0|Not a Club Member and 1|Club Member and get: on the node page Club Member: Not a Club Member and on the node edit page [] Club Member That works for the edit page but is awkward on the node page. If I change the display to 'unformatted' (at admin/content/node-type/my_node_type/display), a 0 or 1 will be displayed on the node page instead of the value label: on the node page Club Member: 0 I would prefer to display YES or NO on the node page and also in a view: Club Member: NO

 

The Solution

Use a custom cck formatter to output YES or NO instead of 1 or 0. If you haven't done this before, it's easier than you might think! It terms of the actual formatter, this one is dead simple. We will have to use couple of hooks to expose the formatter to the Drupal admin UI. 1. Register the formatter with hook_field_formatter_info(). Note the machine name of the integer field type is number_integer. The 'label' you choose will appear in the select list for the display of each integer field on the 'display fields' page (admin/content/node-type/my_node_type/display). The array key – 'mymodule_yes_no_boolean' – can be anything but must match what is used in hook theme.

/**
 * Implementation of hook_field_formatter_info().
 */
function mymodule_field_formatter_info() {
  $formatters = array(
    'mymodule_yes_no_boolean' => array(
      'label' => t('YES or NO'),
      'field types' => array('number_integer'),
      'description' => t('Displays YES or NO.'),      
    )
  );
  return $formatters;
}

2. Register your formatter with hook_theme(). Here the $themes array key is composed of your module name followed by 'formatter' followed by the $formatters array key you used in hook_field_formatter_info(). Declaring a file is not necessary but it is good practice to keep your .module file lighter.

/**
 * Implementation of hook_theme().
 */
function mymodule_theme($existing, $type, $theme, $path) {
  $themes = array(
    'mymodule_formatter_mymodule_yes_no_boolean' => array(
      'arguments' => array('element' => NULL),
      'file' => 'includes/mymodule.theme.inc'
    ),
  );
  return $themes;
}

3. Write the theme function. Since we declared 'includes/mymodule.theme.inc' as the file in which to find the theme function, that's where we'll put it. The function is named 'theme_' followed by the $themes array key we used in hook_theme(). All we need to do is check the $element['#item']['value'] which will be either 0 or 1 (as defined in your key|label pairs), and then we can output whatever we want instead. Actually, if your number_integer field isn't an on/off field then you could have other values, but then you wouldn't choose 'YES or NO' as your formatter!

/**
 * CCK Formatter theme function for single on/off checkbox integer fields.
 */
function theme_mymodule_formatter_mymodule_yes_no_boolean($element) {
  $output = ($element['#item']['value']) ? 'YES' : 'NO';
  return $output;
}

As always, your feedback and other ideas are welcomed.