Abrir enlaces en barra lateral fácilmente en Drupal

página web con sidebar abierta
Solucionex
23
Jul 26

Drupal permite abrir enlaces internos en ventanas modales o la barra lateral, de manera que para determinadas cosas no haga falta cambiar de ventana.

Esto puede hacer directamente añadiendo los atributos necesarios en un enlace. Por ejemplo:

<a
  href="/enlace"
  class="use-ajax"
  data-dialog-type="dialog"
  data-dialog-renderer="off_canvas"
  data-dialog-options="{&quot;width&quot;:600}"
>
</a>

El problema es que esto es engorroso y habría que poner los 3 atributos siempre a cada enlace que se quiera abrir así, por lo que lo ideal es utilizar una función de twig que se encargue de generar los atributos correctos. Para ello es necesario crear una extensión de twig, que aparte hay que definir en el archivo services del módulo donde se vaya a crear:

#archivo mymodule.services.yml

services:
  ...
  mymodule.twig_extension:
    class: Drupal\mymodule\Template\TwigExtension
    tags:
      - { name: twig.extension }
<?php

// Archivo mymodules/src/Template/TwigExtension.php

declare(strict_types=1);

namespace Drupal\mymodule\Template;

/**
 * Custom twig functions.
 */
final class TwigExtension extends AbstractExtension {

  /**
   * {@inheritdoc}
   */
  #[\Override]
  public function getFunctions(): array {
    return [
      new TwigFunction('sidebar_link_attributes', $this->sidebarLinkAttributes(...)),
    ];
  }
  
  /**
   * Generates the needed attributes to open a link in the sidebar.
   */
  public function sidebarLinkAttributes(?int $width = 600): Attribute {
    return new Attribute([
      'class' => 'use-ajax',
      'data-dialog-type' => 'dialog',
      'data-dialog-renderer' => 'off_canvas',
      'data-dialog-options' => Json::encode(['width' => $width, 'minWidth' => $width]),
    ]);
  }
}

De esta manera se le puede especificar un ancho específico a la sidebar. Para usarlo (una vez limpiada la caché tras crear ambos archivos), solo es necesario invocarla en algún enlace en una plantilla. Ejemplos:

{# Plantilla de twig cualquiera #}

{# Es necesario añadir la biblioteca js de ajax, por si no estuviese ya cargada #}
{{ attach_library('core/drupal.ajax') }}

<a href="/otra-pagina" {{ sidebar_link_attributes(1000) }}>
  Enlace a otra página
</a>

{# También se pueden añadir los atributos de sidebar a componentes #}
{{ include("mytheme:button", {
  url: '/otra-pagina',
  attributes: sidebar_link_attributes(),
}) }}
página web con sidebar abierta

Así mismo, también se puede hacer lo mismo pero con una ventana modal. Solamente sería añadir otra función a la extensión de twig:

...

/**
 * {@inheritdoc}
 */
#[\Override]
public function getFunctions(): array {
  return [
    new TwigFunction('sidebar_link_attributes', $this->sidebarLinkAttributes(...)),
    new TwigFunction('modal_link_attributes', $this->modalLinkAttributes(...)),
  ];
}

/**
 * Generates the needed attributes to open a link in a modal.
 */
public function modalLinkAttributes(): Attribute {
  return new Attribute([
    'class' => 'use-ajax',
    'data-dialog-type' => 'modal',
  ]);
}

...
{# Plantilla de twig cualquiera #}

{# Es necesario añadir la biblioteca js de ajax, por si no estuviese ya cargada #}
{{ attach_library('core/drupal.ajax') }}

<a href="/otra-pagina" {{ modal_link_attributes() }}>
  Enlace a otra página
</a>

{# También se pueden añadir los atributos a componentes #}
{{ include("mytheme:button", {
  url: '/otra-pagina',
  attributes: modal_link_attributes(),
}) }}
web con modal abierta

Por último, al ser el valor retornado por la función un objeto de atributos de Drupal, pueden usarse sus funciones, como .addClass() para añadir clases o .setAttribute() para modificar atributos.