Backend Development - Field Formatters

we created a custom Field Type (data storage) and built a Field Widget (data input).

Now we complete the field system by building the final layer: Field Formatters.

If a field type defines how data is stored and a widget defines how data is entered, a field formatter defines how data is displayed.

Field formatters control:

  • How field values are rendered
  • How values appear in different view modes
  • How output is structured
  • How presentation remains separate from storage

This topic continues extending the same weeklydrupal_demo module and the custom rating field we previously created.

By the end of this article, you will understand:

  • What a field formatter is
  • How formatters connect to field types
  • How to create a custom formatter plugin
  • How Drupal renders field output
  • Why separating storage and presentation matters

1. What Is a Field Formatter

A field formatter controls how field data appears when viewing an entity.

Examples you already know:

  • A text field can display as plain text or trimmed text
  • A boolean field can display as "Yes/No" or "True/False"
  • An entity reference can display as a label or a linked label

The same field type can have multiple formatters.

In simple terms:

Field Type = how data is stored
Field Widget = how data is entered
Field Formatter = how data is displayed


2. Where Field Formatters Live

Field formatter plugins live in:

src/Plugin/Field/FieldFormatter

Drupal discovers them using annotations.


3. Creating a Formatter for the Rating Field

We will create a formatter that displays stars instead of numbers.

File path

weeklydrupal_demo/src/Plugin/Field/FieldFormatter/RatingStarsFormatter.php

Code

<?php

namespace Drupal\weeklydrupal_demo\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;

/**
 * Plugin implementation of the 'rating_stars_formatter' formatter.
 *
 * @FieldFormatter(
 *   id = "rating_stars_formatter",
 *   label = @Translation("Rating Stars"),
 *   field_types = {
 *     "rating"
 *   }
 * )
 */
class RatingStarsFormatter extends FormatterBase {

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = [];

    foreach ($items as $delta => $item) {
      $value = $item->value;
      $stars = str_repeat('★', $value);

      $elements[$delta] = [
        '#markup' => $stars,
      ];
    }

    return $elements;
  }

}

4. Understanding the Annotation

@FieldFormatter(
  id = "rating_stars_formatter",
  label = @Translation("Rating Stars"),
  field_types = { "rating" }
)

Explanation:

  • id – Machine name of the formatter
  • label – Appears in field display settings
  • field_types – Defines which field types this formatter supports

This connects the formatter to the rating field type.


5. The viewElements() Method

public function viewElements(FieldItemListInterface $items, $langcode)

This method:

  • Receives stored field values
  • Loops through them
  • Returns a render array

Drupal handles:

  • Caching
  • Theming
  • View modes
  • Integration with Views and REST

6. Understanding $items and $delta

  • $items contains all values of the field
  • $delta represents each value’s index

For multi-value fields, the formatter must handle multiple entries.


7. How Drupal Uses Formatters

When viewing an entity:

  1. Drupal loads the entity
  2. Retrieves field values
  3. Looks up the selected formatter
  4. Calls viewElements()
  5. Merges render arrays into the final page

The formatter never touches database logic. It only controls output.


8. View Modes and Display Configuration

Field formatters can be selected per view mode:

  • Full content
  • Teaser
  • Custom view modes

Each mode can use a different formatter.

This gives Drupal strong flexibility in presentation.


9. Formatter Settings

Formatters can define configurable settings.

Example:

public static function defaultSettings() {
  return [
    'show_max' => TRUE,
  ] + parent::defaultSettings();
}

These settings appear in the "Manage Display" UI.


10. Separation of Responsibilities

Field system architecture encourages separation:

  • Field Type = storage
  • Widget = input
  • Formatter = output

This separation ensures:

  • Clean architecture
  • Reusability
  • Flexibility
  • Scalability

11. Common Mistakes to Avoid

  • Performing business logic inside formatters
  • Hardcoding presentation that belongs in themes
  • Ignoring multi-value behavior
  • Returning strings instead of render arrays

Formatters should focus on transforming stored data into renderable output.


12. Learning by Building: weeklydrupal_demo

Our demo module now includes:

  • Custom field type
  • Custom widget
  • Custom formatter

We now have a complete custom field system.

Next topics will expand into:

  • Entity CRUD
  • Typed Data API
  • Advanced backend processing

13. Why Field Formatters Matter

Understanding field formatters allows you to:

  • Build flexible display systems
  • Support multiple view modes
  • Integrate with Views cleanly
  • Separate data modeling from presentation

This is a key concept for backend Drupal developers who design scalable content systems.