Creación de un formateador de campo
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:
- Implementar la interfaz ContainerFactoryPluginInterface
- Implementar ContainerFactoryPluginInterface::create()
- Sobre-escribir FormatterBase::__construct()
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.