Modal dialogs in Drupal 8

Recently, I am using a lot CTools (Chaos Tools Suite) module. Is a swiss army knife with a lot of features, for example:

  • Modal dialogs
  • Extensible plugins
  • Multistep forms

Using modal dialogs with CTools is very easy, and it also provides tools to easily manage browser requests without Javascript enabled, allowing a graceful degradation.

With Drupal 8, we finally have Views in core. Views module is the most used, and it was created by merlinofchaos. In its 3.x version, it depend on CTools in order to use administration modal dialogs. What's going on with Views in core? Will CTools be in core also? The anser is just NO...

Instead, Views en el core initiative team decided to use jQuery UI Dialog. As it was in Drupal core since 7.x version, why not to use it? Also, is a more generic solution than CTools custom code, and with more options.

There are some examples about how to create modal dialogs in CTools in Drupal 7, and also some examples about how to create CTool modal dialogs with multiple custom styles.

So, how can we do it in Drupal 8? Below, I'll show you a simple example about how to do it, taking into account if user is using Javascript or not:

./modaltest.info.yml

name: 'Modaltest'
type: module
description: 'Modal test'
core: 8.x

./modaltest.module

<?php
  // A .module file is required.

./modaltest.routing.yml

modaltest.page:
  path: '/modaltest'
  defaults:
    _title: 'Modal Test'
    _content: '\Drupal\modaltest\Controller\ModaltestController::page'
  requirements:
    _permission: 'access content'
modaltest.modal:
  path: '/modaltest/modal/{js}'
  defaults:
    _title: Modal
    _content: '\Drupal\modaltest\Controller\ModaltestController::modal'
  requirements:
    _permission: 'access content'
    js: 'nojs|ajax'

./lib/Drupal/modaltest/Controller/ModaltestController.php

<?php

namespace Drupal\modaltest\Controller;

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

class ModaltestController extends ControllerBase {

  public function page() {
    return array(
      '#type' => 'markup',
      '#markup' => l(
        t('Link'),
        'modaltest/modal/nojs',
        array(
          'attributes' => array(
            'class' => 'use-ajax',
          ),
        )
      ),
      '#attached' => array(
        'library' => array(
          array('system', 'drupal.ajax'),
        ),
      ),
    );
  }

  public function modal($js = 'nojs') {
    if ($js == 'ajax') {
      $options = array(
        'width' => '80%',
      );
      $response = new AjaxResponse();
      $response->addCommand(
        new OpenModalDialogCommand(t('Modal'), t('This is the modal with Javascript.'), $options)
      );
      return $response;
    }
    else {
      return t('This is the page without Javascript.');      
    }
  }

}

If we are using HTML5, we can use attribute data-options in order to configure the modal dialog, and the attribute data-accepts if we are allowed to return the same answer with and without Javascript, as explained in this article.

Below, I show how modaltest.routing.yml and ModaltestController.php will look in that case:

./modaltest.routing.yml

modaltest.page:
  path: '/modaltest'
  defaults:
    _title: 'Modal Test'
    _content: '\Drupal\modaltest\Controller\ModaltestController::page'
  requirements:
    _permission: 'access content'
modaltest.modal:
  path: '/modaltest/modal'
  defaults:
    _title: Modal
    _content: '\Drupal\modaltest\Controller\ModaltestController::modal'
  requirements:
    _permission: 'access content'

./lib/Drupal/modaltest/Controller/ModaltestController.php

<?php

namespace Drupal\modaltest\Controller;

use Drupal\Core\Controller\ControllerBase;

class ModaltestController extends ControllerBase {

  public function page() {
    return array(
      '#type' => 'markup',
      '#markup' => l(
        t('Link'),
        'modaltest/modal',
        array(
          'attributes' => array(
            'class' => 'use-ajax',
            'data-accepts' => 'application/vnd.drupal-modal',
            'data-dialog-options' => '{"width": "80%"}',
          ),
        )
      ),
      '#attached' => array(
        'library' => array(
          array('system', 'drupal.ajax'),
        ),
      ),
    );
  }

  public function modal() {
    return t('This is the page without Javascript and the modal with Javascript.');      
  }

}

1 Comment

hey

I have been surfing online more than three hours today, yet I never found any interesting article like yours. It is pretty worth enough for me. In my view, if all website owners and bloggers made good content as you did, the web will be a lot more useful than ever before.

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.