¿Cómo crear ventanas modales en drupal 8?

Author Top
Luis Eduardo Telaya Escobedo

1. ¿Qué es una ventana modal?

La ventana modal es una ventana secundaria que requiere que los usuarios interactuen con esta, antes de que pueda volver a operar la solicitud principal. Evitando así que el flujo de trabajo en la ventana principal de la aplicación continue.

2. ¿Cómo crear una ventana modal en Drupal 8?

Primeramente necesitaremos crear un módulo con Drupal 8! Pueden usar el proyecto Drupal Console para crear un módulo con un controller incluido como se puede ver en la siguiente imagen.

Luego de generado debemos modificar el archivo modules/custom/mymodule/mymodule.routing.yml para asociar una ruta a los metodos en el controller que vamos a declarar mas tarde.

Veamos como quedaría el archivo de routing:

mymodule.default_controller_index:
  path: '/mymodule/index'
  defaults:
    _controller: '\Drupal\mymodule\Controller\DefaultController::index'
    _title: 'mymodule Title'
  requirements:
    _permission: 'access content'
    
mymodule.modal:
  path: '/mymodule/modal'
  defaults:
    _controller: '\Drupal\mymodule\Controller\DefaultController::modal'
    _title: 'mymodule Title'
  requirements:
    _permission: 'access content' 

Ahora modificaremos la clase del controller para incluir los métodos index y modal, como se muestra a continuación.

<?php

/**
 * @file
 * Contains Drupal\mymodule\Controller\DefaultController.
 */

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Ajax\AjaxResponse; 
use Drupal\Core\Ajax\OpenModalDialogCommand;
use Drupal\Core\Url;

/**
 * Class DefaultController.
 *
 * @package Drupal\mymodule\Controller
 */
class DefaultController extends ControllerBase {

  /**
   * Index.
   *
   * @return string
   *   Return Hello string.
   */
  public function index() {
    $attributes = array(
      'attributes' => array(
        'class' => array('use-ajax'),
        'data-accepts' => 'application/vnd.drupal-dialog',
      ),
    );
    // Let's create the link.
    $url = Url::fromRoute('mymodule.modal', [], $attributes);
    $internal_link = \Drupal::l(t('Open a Modal'), $url);
    return [
        '#type' => 'markup',
        '#markup' => $internal_link,
    ];
  }
  
  /**
   * Displays modal.
   */
  public function modal() {
    $content['#attached']['library'][] = 'core/drupal.dialog.ajax';
    $response = new AjaxResponse();
    $title = $this->t('Title of Modal');
    $content['#markup'] = 'Content of Modal';
    $response->addCommand(new OpenModalDialogCommand($title, $content));
    return $response;
  }
}

En la primera parte creamos un simple enlace, pero con atributos especiales como son class y agregando elementos de data-accepts y este link se creara usando la Ruta a nuestra ventana modal. Como resultado tendremos un controlador similar a la siguiente imagen:

 Pagina con título y un enlace para abrir un modal

Al hacer clic en este link abriría la ventana modal,  al método modal de nuestro modulo, para hacer la implementación debemos realizar los siguientes pasos

  • Agregar la libreria del core drupal.dialog.ajax para abrir el modal
  • Instanciar un objeto AjaxResponse()
  • Establecer un título y el contenido del modal que debe estar en la propiedad '#markup';
  • La instancia AjaxResponse usar el método addCommand, en donde se agrega una instancia de OpenModalDialog

Al final obtendríamos una ventana modal similar a la siguiente imagen.

Modal en drupal 8

3. Usuarios anónimos y librerías

Sin embargo esta ventana modal solo funciona con usuario admin! y la razón es que jquery, ajax y otras librerias no están cargadas por defecto ver este enlace  http://www.webomelette.com/drupal-8-core-javascript-files-anonymous-users.

Para permitir que estas librerías estén disponibles para todos los usuarios deberemos realizar los siguientes cambios en el modulo

Creamos un archivo dentro de nuestro modulo llamado mymodules.libraries.yml con las dependencias necesarias de librerías de js, lo que forzara a que estas librerías se carguen por defecto. Por lo tanto podríamos ya quitar la inclusión de la librería core/drupal.dialog.ajax del método modal de nuestro controlador.

my_scripts:
  version: VERSION
  js:
    js/scripts.js: {}
  dependencies:
    - core/jquery
    - core/drupal.ajax
    - core/drupal
    - core/drupalSettings
    - core/jquery.once
    - core/drupal.dialog.ajax

Además debemos modificar el archivo mymodule.info.yml para agregar la sección my_scripts.

name: mymodule
type: module
description: My Awesome Module
core: 8.x
package: Other
libraries:
  - my_scripts  

Para terminar implemetnamos el hook hook_page_attachments():

/**
 * Implements hook_page_attachments().
 */
function mymodule_page_attachments_alter(array &$page) {
  $page['#attached']['library'][] = 'mymodule/my_scripts';
}

Cualquier consulta/duda con mucho gusto estare para apoyar.

Happy codding!