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

Creación de un estilo de visualización Views para Drupal

20/06/2025, by Ivan

Crear un plugin de estilo de visualización Views puede parecer una tarea compleja, pero es más fácil de lo que parece. Aquí tienes una guía paso a paso sobre cómo hacerlo, con el código fuente.

Puedes descargar el código listo aquí: TARDIS (aunque todavía está en desarrollo). Y si necesitas una introducción a los módulos de Drupal 8, aquí tienes la guía práctica para crear módulos básicos de Drupal 8.

.info.yml

Comienza creando una carpeta llamada tardis para tu módulo en /modules/custom. Coloca dentro un archivo llamado tardis.info.yml con el siguiente código:

name: TARDIS
type: module
description: 'Provee un estilo de visualización Views que renderiza una lista de enlaces de años y meses al contenido en orden cronológico inverso.'
package: Views
core: '8.x'
dependencies:
  - drupal:views

Classy

Ahora es momento de crear la clase del plugin. Crea un archivo llamado Tardis.php dentro de src/Plugin/views/style e inserta el siguiente código:

<?php

namespace Drupal\tardis\Plugin\views\style;

use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\style\StylePluginBase;

/**
 * Plugin de estilo para renderizar una lista de años y meses
 * en orden cronológico inverso enlazados al contenido.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "tardis",
 *   title = @Translation("TARDIS"),
 *   help = @Translation("Renderiza una lista de años y meses en orden cronológico inverso enlazados al contenido."),
 *   theme = "views_view_tardis",
 *   display_types = { "normal" }
 * )
 */
class Tardis extends StylePluginBase {

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['path'] = ['default' => 'tardis'];
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

    // Prefijo de ruta para los enlaces TARDIS.
    $form['path'] = [
      '#type' => 'textfield',
      '#title' => t('Ruta de enlace'),
      '#default_value' => isset($this->options['path']) ? $this->options['path'] : 'tardis',
      '#description' => t('Prefijo de ruta para cada enlace TARDIS, p.ej. example.com<strong>/tardis/</strong>2015/10.'),
    ];

    // Formato de fecha para el mes.
    $form['month_date_format'] = [
      '#type' => 'textfield',
      '#title' => t('Formato de fecha para mes'),
      '#default_value' => isset($this->options['month_date_format']) ? $this->options['month_date_format'] : 'm',
      '#description' => t('Parámetro válido de la <a href="@url" target="_blank">función Date de PHP</a> para mostrar los meses.', ['@url' => 'http://php.net/manual/en/function.date.php']),
    ];

    // Si los enlaces de mes deben estar anidados dentro de los años.
    $options = [
      1 => 'sí',
      0 => 'no',
    ];
    $form['nesting'] = [
      '#type' => 'radios',
      '#title' => t('Anidamiento'),
      '#options' => $options,
      '#default_value' => isset($this->options['nesting']) ? $this->options['nesting'] : 1,
      '#description' => t('¿Deben los meses estar anidados dentro de los años? <br />
        Ejemplo:
        <table style="width:100px">
          <thead>
              <th>Anidamiento</th>
              <th>Sin anidamiento</th>
          </thead>
          <tbody>
            <td>
              <ul>
                <li>2016
                  <ul>
                    <li>03</li>
                    <li>02</li>
                    <li>01</li>
                  </ul>
                </li>
              </ul>
            </td>
            <td>
              <ul>
                <li>2016/03</li>
                <li>2016/02</li>
                <li>2016/01</li>
              </ul>
            </td>
          </tbody>
        </table>
      '),
    ];

    // Clases CSS adicionales.
    $form['classes'] = [
      '#type' => 'textfield',
      '#title' => t('Clases CSS'),
      '#default_value' => isset($this->options['classes']) ? $this->options['classes'] : 'view-tardis',
      '#description' => t('Clases CSS para personalización adicional de esta página TARDIS.'),
    ];
  }

}

Veamos algunos fragmentos:

 * @ViewsStyle(
 *   id = "tardis",
 *   title = @Translation("TARDIS"),
 *   help = @Translation("Renderiza una lista de años y meses en orden cronológico inverso enlazados al contenido."),
 *   theme = "views_view_tardis",
 *   display_types = { "normal" }
 * )

Estos comentarios son importantes. Establecen la base para nuestro plugin. Si olvidas agregarlos, el código no funcionará correctamente.

class Tardis extends StylePluginBase {

La definición básica del plugin. Nuevamente, esto es necesario.

  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['path'] = ['default' => 'tardis'];
    return $options;
  }

La capacidad de definir opciones básicas y un valor predeterminado importante para nuestro plugin. Está aquí porque este plugin debe ser configurable.

  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);

Avanzando, creamos el formulario real de opciones con campos, casi como formularios de configuración normales. Para más información, por favor consulta la referencia del API de formularios.

.file

El archivo .module no es obligatorio en Drupal 8, pero es donde debe estar la información del tema:

<?php

/**
 * @file
 * Ayuda del módulo TARDIS Views y funciones de tema.
 */

/**
 * Implementa hook_theme().
 */
function tardis_theme($existing, $type, $theme, $path) {
  // Guardar funciones de preprocesamiento de tema de TARDIS en un archivo .inc separado.
  \Drupal::moduleHandler()->loadInclude('tardis', 'inc', 'tardis.theme');

  return [
    'tardis' => [
      'file' => 'tardis.theme.inc',
    ],
  ];
}

En esencia, delegamos la función de preprocesamiento a un archivo separado para mantener todo organizado.

Archivo .theme.inc

Crea un archivo llamado tardis.theme.inc en el directorio de nuestro módulo e incluye el siguiente código:

<?php

/**
 * @file
 * Tema para las vistas TARDIS.
 */
function template_preprocess_views_view_tardis(&$variables) {
  // Opciones de la vista configuradas por el usuario.
  $options = $variables['view']->style_plugin->options;

  // Construir un array bidimensional con años y meses.
  $time_pool = [];

  foreach ($variables['view']->result as $id => $result) {
    $created = $result->node_field_data_created;
    $created_year = date('Y', $created);
    // Formato de fecha para el mes.
    $month_date_format = isset($options['month_date_format']) ? $options['month_date_format'] : 'm';
    $created_month_digits = date('m', $created);
    $created_month = date($month_date_format, $created);
    $time_pool[$created_year][$created_month_digits] = "$created_month";
  }

  $options['time_pool'] = $time_pool;

  // Actualizar opciones para Twig.
  $variables['options'] = $options;
}

Este código básicamente toma todas las fechas de creación de los nodos y crea un arreglo asociativo que se pasa a la plantilla para el renderizado final, junto con otras opciones definidas en el formulario que permanecen intactas.

Twig it out

Ahora, para la salida del módulo, crea un archivo views-view-tardis.html.twig en una carpeta llamada templates. ¿Pero por qué este nombre? ¿Recuerdas los comentarios al inicio de esta lección?

* theme = "views_view_tardis",

Esto significa que la plantilla debe encontrarse en la ubicación por defecto (/templates) con ese nombre, solo con guiones en lugar de guiones bajos y con extensión .html.twig al final.

Sobre el código:

{#
/**
 * Implementación de tema por defecto para Views para mostrar un archivo TARDIS.
 *
 * Variables disponibles:
 * - options: Opciones del plugin de estilo de la vista:
 *   - classes: Clases CSS.
 *   - nesting: Si los meses deben estar anidados dentro de los años.
 *   - path: Ruta del enlace. Ej.: example.com/TARDIS/2016/03
 *   - time_pool: Array bidimensional que contiene años y meses con contenido.
 *
 * @see template_preprocess_views_view_tardis()
 *
 * @ingroup themeable
 */
#}
{%
  set classes = [
    'views-view-tardis',
    options.classes
  ]
%}
<div{{ attributes.addClass(classes) }}>
  <ul>
    {% for key, item in options.time_pool %}
      {% if options.nesting == 1 %}
        <li><a href="/{{ options.path }}/{{ key }}">{{ key }}</a><ul>
        {% for subkey, subitem in item %}
          <li><a href="/{{ options.path }}/{{ key }}/{{ subkey }}">{{ subitem }}</a></li>
        {% endfor %}
        </ul></li>
      {% else %}
        {% for subkey, subitem in item %}
          <li><a href="/{{ options.path }}/{{ key }}/{{ subkey }}">{{ subitem }}</a></li>
        {% endfor %}
      {% endif %}
    {% endfor %}
  </ul>
</div>

Primero, se recomienda extraer todas las variables pasadas como arreglo asociativo $variable al principio del archivo. Se guardan ordenadamente en $variable['options'] — o, como lo llamaría Twig, variables.options.

Luego establecemos algunas clases para nuestra vista, como se definió en el formulario de opciones:

{%
  set classes = [
    'views-view-tardis',
    options.classes
  ]
%}

Y recuérdalas:

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

El resto del código se dedica a extraer los meses y años con entradas y mostrar la lista en HTML. Aquí es importante notar el ciclo for:

{% for key, item in options.time_pool %}

Esto genera cada enlace correctamente. Por ejemplo:

<li><a href="/{{ options.path }}/{{ key }}/{{ subkey }}">{{ subitem }}</a></li>

Un poco más

Por último, pero no menos importante: debemos crear una vista por defecto y exportarla para facilitarla a los usuarios. Deberías notar que en /config/install/views.view.tardis.yml ya hay una vista por defecto. Esta vista por defecto estará disponible tan pronto como los usuarios activen el módulo.

La creé y exporté mediante el formulario de exportación única en admin/config/development/configuration/single/export, siguiendo el excelente tutorial de Subhojit Paul.

¡Eso es todo!

¡Ahora podrás escribir tu propio plugin de estilo para Views en Drupal 8! Deja tu comentario abajo. ¡Feliz codificación!

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.