Paragraph Behaviors, añadiendo configuración a los paragraphs

paragraphs logo
Solucionex
07
Nov 24

TL;DR: Usando los behaviors, los paragraphs en Drupal permiten configuraciones sin necesidad de crear campos adicionales en el propio paragraph.

Los behaviors (comportamientos) son una funcionalidad poco documentada (algo que no es de sorprender en Drupal, por desgracia) que permite configurar el comportamiento / visualización de los paragraphs. Esto puede hacerse también de manera "normal" añadiendo campos cuyo valor sirva para pintarlos de una manera u otra por ejemplo, pero usando los behaviors se evita la creación de tablas específicas en la base de datos, ya que los datos de los behaviors están serializados dentro de la tabla principal de paragraphs.

Para este post, se usa como ejemplo un behavior que permite modificar la alineación horizontal de un paragraph. En este caso, para un botón.

Los behaviors son una clase de drupal usando la anotación "ParagraphsBehavior" (todavía no funciona con atributos nativos de php).

Clase PHP del behavior

<?php

namespace Drupal\mymodule\Plugin\paragraphs\Behavior;

use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\paragraphs\ParagraphInterface;
use Drupal\paragraphs\ParagraphsBehaviorBase;

/**
 * Paragraphs behaviour plugin for horizontal alignment.
 *
 * @ParagraphsBehavior(
 *   id = "horizontal_alignment",
 *   label = @Translation("Horizontal alignment"),
 *   description = @Translation("Configure horizontal alignment for this paragraph."),
 * )
 */
class AlignmentBehavior extends ParagraphsBehaviorBase {

  /**
   * {@inheritdoc}
   */
  public function view(array &$build, Paragraph $paragraph, EntityViewDisplayInterface $display, $view_mode) {
    $alignment = $paragraph->getBehaviorSetting($this->getPluginId(), 'horizontal_alignment', 'left');
    $build['#settings']['horizontal_alignment'] = $alignment;
  }

  /**
   * {@inheritdoc}
   */
  public function buildBehaviorForm(ParagraphInterface $paragraph, array &$form, FormStateInterface $form_state) {
    $form['horizontal_alignment'] = [
      '#type' => 'radios',
      '#title' => $this->t('Horizontal alignment'),
      '#default_value' => $paragraph->getBehaviorSetting($this->getPluginId(), 'horizontal_alignment', 'left'),
      '#options' => [
        'left' => $this->t('Left'),
        'center' => $this->t('Center'),
        'right' => $this->t('Right'),
      ],
      '#required' => TRUE,
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary(Paragraph $paragraph) {
    $horizontal_alignment = $paragraph->getBehaviorSetting($this->getPluginId(), 'horizontal_alignment', 'left');
    return [
      $this->t('Horizontal alignment: @alignment', [
      // phpcs:ignore
      '@alignment' => $this->t(ucfirst($horizontal_alignment)),
      ]),
    ];
  }

}

Estructura

Una vez creada la clase, y tras limpiar caché para que drupal descubra el nuevo behavior, se crea un nuevo tipo de paragraph "Botón" y se selecciona el behavior de alineación horizontal.

formulario paragraph con behavior

Tras esto, se añade un campo enlace al paragraph de manera normal via UI y en un tipo de contenido (página básica, por ejemplo), se añade un campo paragraph para poder añadir el botón. Una vez se entre al formulario de nodo, se verán dos nuevas pestañas en el form del paragraph:

Contenido, donde están los campos habituales del paragraph, en este caso un enlace.

formulario de paragrpah

Y Behavior (en este caso traducido como "configuración"), donde se genera el formulario de las configuraciones.

formulario behavior paragraph

Una vez se guarde el nodo, se guardará la configuración del paragraph.

Cambiar la manera en la que se muestra el paragraph

Ahora falta pintar el botón de manera que respete la configuración de alineación. Para ello, hay que sobreescribir la plantilla de paragraph con la específica para este tipo de paragraph. Ejemplo de cómo se puede usar (usando clases de tailwind):

{# Obtener la configuración desde el array $build (función "view" de la clase del behavior) #}
{% set horizontal_alignment = elements['#settings'].horizontal_alignment %}
{#
  Versión alternativa, obtener valor directamente desde el paragraph.

  Los argumentos son [ID DEL PLUGIN], [ID DE LA CONFIG DEL BEHAVIOR], [VALOR POR DEFECTO].
#}
{% set horizontal_alignment = paragraph.getBehaviorSetting('horizontal_alignment', 'horizontal_alignment', 'left') %}

{# Cambiar las clases dependiendo de la alineación #}
{% set classes = [
  'paragraph',
  'paragraph--type--' ~ paragraph.bundle|clean_class,
  view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
  not paragraph.isPublished() ? 'paragraph--unpublished',
  horizontal_alignment == 'center' ? 'flex justify-center',
  horizontal_alignment == 'right' ? 'flex justify-end',
] %}

<div{{ attributes.addClass(classes) }}>
  {{ content }}
</div>

De esta manera, dependiendo de si el valor es "center" o "right" aparecerá el botón en su lugar correspondiente (para izquierda no hace falta, ya que es la colocación por defecto del elemento):

4
5
6
Drupal
Paragraphs
Behaviors