logo

Extra Block Types (EBT) - Nueva experiencia con Layout Builder❗

Extra Block Types (EBT): tipos de bloques con estilo y personalizables: Presentaciones de diapositivas, Pestañas, Tarjetas, Acordeones y muchos más. Configuraciones integradas para fondo, DOM Box y plugins de JavaScript. Experimenta hoy el futuro de la construcción de diseños.

Módulos de demostración EBT Descargar módulos EBT

❗Extra Paragraph Types (EPT) - Nueva experiencia con Paragraphs

Extra Paragraph Types (EPT): conjunto de módulos basado en párrafos de forma análoga.

Módulos de demostración EPT Descargar módulos EPT

Scroll
20/06/2025, by Ivan

Menu

Un módulo de formateo de campos formatea los datos del campo para que sean visibles para el usuario final. Los formateadores de campo se definen como plugins, por lo que se recomienda revisar la API de plugins antes de comenzar a escribir un nuevo formateador de campos.

Clase del formateador de campo

Archivo: /modules/random/src/Plugin/Field/FieldFormatter/RandomDefaultFormatter.php

<?php

namespace Drupal\random\Plugin\Field\FieldFormatter;

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

/**
 * Implementación del plugin 'Random_default'.
 *
 * @FieldFormatter(
 *   id = "Random_default",
 *   label = @Translation("Texto aleatorio"),
 *   field_types = {
 *     "Random"
 *   }
 * )
 */
class RandomDefaultFormatter extends FormatterBase {

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];
    $summary[] = $this->t('Muestra la cadena aleatoria.');
    return $summary;
  }

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $element = [];

    foreach ($items as $delta => $item) {
      // Renderiza cada elemento como marcado.
      $element[$delta] = ['#markup' => $item->value];
    }

    return $element;
  }

}

Configuraciones del formateador

Si tu formateador requiere configuraciones personalizadas, debes hacer tres pasos:

  • Sobre-escribir PluginSettingsBase::defaultSettings() para definir valores por defecto
  • Crear un esquema de configuración para las opciones definidas
  • Crear un formulario para permitir que los usuarios cambien las configuraciones

Paso 1: Sobre-escribe PluginSettingsBase::defaultSettings() para definir valores por defecto

/**
 * {@inheritdoc}
 */
public static function defaultSettings() {
  return [
    // Declara una opción llamada 'text_length' con valor por defecto 'short'
    'text_length' => 'short',
  ] + parent::defaultSettings();
}

Paso 2: Crea un esquema de configuración para tus opciones

El esquema va en:

[RAIZ_DEL_MODULO]/config/schema/[NOMBRE_DEL_MODULO].schema.yml

En este archivo defines el tipo de datos para las opciones creadas en defaultSettings():

Por ejemplo, el parámetro 'text_length' es una cadena, así que el esquema será:

field.formatter.settings.[ID_DEL_FORMATTER]:
  type: mapping
  label: 'Longitud del texto para [NOMBRE_DEL_FORMATTER]'
  mapping:
    text_length:
      type: string
      label: 'Longitud del texto'

Paso 3: Crea un formulario para que los usuarios cambien la configuración

Este formulario se crea sobre-escribiendo FormatterBase::settingsForm().

No olvides añadir el namespace para FormStateInterface al inicio del archivo PHP.

use Drupal\Core\Form\FormStateInterface;
/**
 * {@inheritdoc}
 */
public function settingsForm(array $form, FormStateInterface $form_state) {
  $form['text_length'] = [
    '#title' => $this->t('Longitud del texto'),
    '#type' => 'select',
    '#options' => [
      'short' => $this->t('Corto'),
      'long' => $this->t('Largo'),
    ],
    '#default_value' => $this->getSetting('text_length'),
  ];

  return $form;
}

Uso de #ajax en formularios de configuración

Usar #ajax en formularios de configuración no es trivial, ya que el fragmento creado por settingsForm() no está en la raíz del formulario sino profundamente anidado. En el siguiente ejemplo hay dos configuraciones: display_type (que puede ser 'label' o 'entity') y entity_display_mode (que puede ser 'full' o 'teaser'). El modo de visualización solo se muestra si display_type es 'entity'.

public function settingsForm(array $form, FormStateInterface $form_state) {
  $form['display_type'] = [
    '#title' => $this->t('Tipo de visualización'),
    '#type' => 'select',
    '#options' => [
      'label' => $this->t('Etiqueta'),
      'entity' => $this->t('Entidad'),
    ],
    '#default_value' => $this->getSetting('display_type'),
    '#ajax' => [
      'wrapper' => 'private_message_thread_member_formatter_settings_wrapper',
      'callback' => [$this, 'ajaxCallback'],
    ],
  ];

  $form['entity_display_mode'] = [
    '#prefix' => '<div id="private_message_thread_member_formatter_settings_wrapper">',
    '#suffix' => '</div>',
  ];

  // Obtener el nombre del campo actual
  $field_name = $this->fieldDefinition->getItemDefinition()->getFieldDefinition()->getName();
  // Clave para la configuración que se quiere recuperar
  $setting_key = 'display_type';

  // Intentar obtener el valor del estado del formulario (no estará en la carga inicial)
  if ($value = $form_state->getValue(['fields', $field_name, 'settings_edit_form', 'settings', $setting_key])) {
    $display_type = $value;
  }
  // En la carga inicial, obtener el valor por defecto
  else {
    $display_type = $this->getSetting('display_type');
  }

  if ($display_type == 'entity') {
    $form['entity_display_mode']['#type'] = 'select';
    $form['entity_display_mode']['#title'] = $this->t('Modo de visualización');
    $form['entity_display_mode']['#options'] = [
      'full' => $this->t('Completo'),
      'teaser' => $this->t('Resumen'),
    ];
    $form['entity_display_mode']['#default_value'] = $this->getSetting('entity_display_mode');
  }
  else {
    // Forzar que el elemento se renderice (para que el contenedor AJAX se renderice), incluso cuando no haya valor seleccionado
    $form['entity_display_mode']['#markup'] = '';
  }

  return $form;
}

Luego crea la función callback ajax que retorna el elemento correspondiente del formulario:

public function ajaxCallback(array $form, FormStateInterface $form_state) {
  $field_name = $this->fieldDefinition->getItemDefinition()->getFieldDefinition()->getName();
  $element_to_return = 'entity_display_mode';

  return $form['fields'][$field_name]['plugin']['settings_edit_form']['settings'][$element_to_return];
}

Inyección de dependencias en formateadores de campo

Usar inyección de dependencias en formateadores requiere tres pasos:

1) Implementar ContainerFactoryPluginInterface

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;

class MyFormatter extends FormatterBase implements ContainerFactoryPluginInterface {

2) Implementar ContainerFactoryPluginInterface::create()

Este ejemplo inyecta el servicio entity.manager en el formateador:

use Symfony\Component\DependencyInjection\ContainerInterface;

public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  return new static(
    $plugin_id,
    $plugin_definition,
    $configuration['field_definition'],
    $configuration['settings'],
    $configuration['label'],
    $configuration['view_mode'],
    $configuration['third_party_settings'],
    // Agrega aquí los servicios que deseas inyectar
    $container->get('entity.manager')
  );
}

3) Sobrescribir FormatterBase::__construct()

Sobre-escribe el constructor en FormatterBase, asegúrate de llamar al padre y luego guarda el servicio en una propiedad de la clase:

use Drupal\Core\Field\FieldDefinitionInterface;

/**
 * El servicio de entity manager
 *
 * @var \Drupal\Core\Entity\EntityManagerInterface
 */
protected $entityManager;

/**
 * Construye un objeto MyFormatter.
 *
 * @param string $plugin_id
 *   El plugin_id para la instancia.
 * @param mixed $plugin_definition
 *   La definición del plugin.
 * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
 *   Definición del campo de entidad.
 * @param array $settings
 *   Configuraciones del formateador.
 * @param string $label
 *   Etiqueta de visualización del formateador.
 * @param string $view_mode
 *   Modo de visualización.
 * @param array $third_party_settings
 *   Configuraciones de terceros.
 * @param \Drupal\Core\Entity\EntityManagerInterface $entityManager
 *   Servicio entity manager.
 */
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, EntityManagerInterface $entityManager) {
  parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);

  $this->entityManager = $entityManager;
}

Ahora puedes usar $this->entityManager en cualquier lugar dentro de tu clase formateadora.

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.