Drupal 8 - Custom field formatter

Submitted by superadmin on Sun, 01/03/2016 - 14:23

Thanks to the Object Oriented approach adopted in Drupal 8,  working with field extension in terms of widgets and formatters have become much easier. Gone are the days where you had to copy huge junks of code to use in your custom formatter. Now you just extend an exisiting formatter and change the bit you want to override.

Creating a new custom formatter is a really straightforward process. I am going to assume you already have a module that you want to place the field formatter in. 

We will be creating a twitter text field formatter that links user handles and hashtags to twitter.

First we create the following folder structure:

field formatter path

Next create our field formatter class php file in mymodule/src/Plugin/Field/FieldFormatter.

Our class will extend the FormatterBase abstract class. The only abstract method we need to implement is

public function viewElements(FieldItemListInterface $items, $langcode);

The class will look like the following:

<?php

namespace Drupal\mymodule\Plugin\Field\FieldFormatter;

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

  /**
  * Twitter field formatter.
  *
  * @FieldFormatter(
  *   id = "twitter",
  *   label = @Translation("Twitter"),
  *   field_types = {
  *     "text_with_summary",
  *     "string",
  *      "text"
  *    }
  * )
  *
  */
class TwitterFormatter extends FormatterBase {
  protected $twitter_base_url = 'https://twitter.com';

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = array();

    foreach ($items as $delta => $item) {
      $item->value = $this->filter_username($item->value);
      $item->value = $this->filter_hashtag($item->value);
      $elements[$delta] = array(
        '#type' => 'processed_text',
        '#text' => $item->value,
        '#format' => $item->format,
        '#langcode' => $item->getLangcode(),
      );
    }
    return $elements;
  }

  /**
   * Callback for twitter @username converter.
   */
  public function filter_username($text) {
    $prefix = '@';
    $destination = $this->twitter_base_url . '/';
    return $this->filter_text($text, $prefix, $destination);
  }

  /**
   * Callback for twitter #hashtag converter.
   */
  public function filter_hashtag($text) {
    $prefix = '#';
    $destination = $this->twitter_base_url . '/search?q=%23';
    return $this->filter_text($text, $prefix, $destination);
  }

  /**
   * Converts Twitter-style @usernames and #hashtags into actual links.
   */
  public function filter_text($text, $prefix, $destination) {
    $replacement = '<a href="' . $destination . '${1}">' . $prefix . '${1}</a>';
    return preg_replace("/$prefix(\w+)/ui", $replacement, $text);
  }

}

The formatter is detected because we are using the annotation-based plugin

 

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.