Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

Four new Ajax Commands have been added to core to manage dialog and modal windows. All of the following code examples should appear within a controller method unless otherwise stated.

To open a dialog window:

  use Drupal\Core\Ajax\AjaxResponse;
  use Drupal\Core\Ajax\OpenDialogCommand;

  // ... Other code ...
  $content = "Something to show in the dialog";
  $title = "Hi, I'm a Dialog";
  $response = new AjaxResponse();
  $response->addCommand(new OpenDialogCommand('#some-element', $title, $content, ['width' => '700']));
  return $response;

To open a modal window:

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

  // ... Other code ...
  $content = "Something to show in the modal";
  $title = "Hi, I'm a Modal";
  $response = new AjaxResponse();
  $response->addCommand(new OpenModalDialogCommand($title, $content, ['width' => '700']));
  return $response;

To close a dialog/modal:

  use Drupal\Core\Ajax\AjaxResponse;
  use Drupal\Core\Ajax\CloseModalDialogCommand;
  $command = new CloseModalDialogCommand();
  $response = new AjaxResponse();
  $response->addCommand($command);
  return $response;

  // .. For a dialog.
  use Drupal\Core\Ajax\AjaxResponse;
  use Drupal\Core\Ajax\CloseDialogCommand;
  $command = new CloseDialogCommand('#some-element');
  $response = new AjaxResponse();
  $response->addCommand($command);
  return $response;

To allow a link to return a modal

  • Ensure the core/drupal.ajax library is added to the page using #attached.
  • Ensure the path is handled by a route (entry in MYMODULE.routing.yml and not a mymodule_menu())
  • Ensure the link has class 'use-ajax'
  • Ensure the link has data-dialog-type attribute of either application/vnd.drupal-modal or application/vnd.drupal-dialog, as appropriate
  • If you want to control the size etc of the dialog, you can use the data-dialog-options attribute - which accepts encoded json of any valid option accepted by jQuery UI Dialog.
  1. Open simple link in modal dialog.
  2.   $form['link'] = [
        '#markup' => \Drupal::l('Make mine a modal', Url::fromRoute('mymodule.some_modal_route_name', [], [
          'attributes' => [
            'class' => ['use-ajax'],
            'data-dialog-type' => 'modal',
            'data-dialog-options' => json_encode(['height' => 400, 'width' => 700]),
          ],
         ]))
      ];
    
  3. Open form link element in modal dialog.
  4.   // Dialog behavior applied to a #type => 'link'.
        $form['link'] = [
          '#markup' => \Drupal::l('Make mine a modal', Url::fromRoute('mymodule.some_modal_route_name')),
          '#attributes' => [
            'class' => ['use-ajax'],
            'data-dialog-type' => 'modal',
            'data-dialog-options' => json_encode(['height' => 400, 'width' => 700]),
          ],
        ];
    
  5. Open theme_links/form operations element in modal dialog.
  6.   // Dialog behavior applied to links rendered by theme_links().
      $form['links'] = [
        '#theme' => 'links',
        '#links' => [
          'link2' => [
            'title' => 'Link 2 (modal)',
            'url' => Url::fromRoute('ajax_test.dialog_contents'),
            'attributes' => [
              'class' => ['use-ajax'],
              'data-dialog-type' => 'modal',
              'data-dialog-options' => json_encode(['width' => 400]),
            ],
          ],
          'link3' => [
            'title' => 'Link 3 (non-modal)',
            'url' => Url::fromRoute('ajax_test.dialog_contents'),
            'attributes' => [
              'class' => ['use-ajax'],
              'data-dialog-type' => 'dialog',
              'data-dialog-options' => json_encode([
                'target' => 'ajax-test-dialog-wrapper-1',
                'width' => 800,
              ]),
            ],
          ],
          'link4' => [
            'title' => 'Link 4 (close non-modal if open)',
            'url' => Url::fromRoute('ajax_test.dialog_close'),
            'attributes' => [
              'class' => ['use-ajax'],
            ],
          ],
        ],
      ];
    
  7. Open buttons/form action element in modal dialog.
  8.   $form['button1'] = [
        '#type' => 'submit',
        '#name' => 'button1',
        '#value' => 'Button 1 (modal)',
        '#ajax' => [
          'callback' => 'ajax_test_dialog_form_callback_modal',
        ],
      ];
    /**
     * AJAX callback handler for ajax_test_dialog_form().
     */
    function ajax_test_dialog_form_callback_modal($form, &$form_state) {
      $content['#markup'] = "Something to show in the modal";
      $content['#attached']['library'][] = 'core/drupal.dialog.ajax';
      $title = "Hi, I'm a Modal";
      $response = new AjaxResponse();
      $response->addCommand(new OpenModalDialogCommand($title, $content, ['width' => '700']));
      return $response;
    }
    

Using #ajax instead of #attribute

use element #ajax property ['accepts' => 'application/vnd.drupal-modal'] instead of #attributes.
This is same as above 2.

$form['link'] = [
    '#type' => 'link',
    '#title' => 'Link 1 (modal)',
    '#url' => Url::fromRoute('ajax_test.dialog_contents'),
    '#ajax' => [
      'dialogType' => 'modal',
      'dialog' => ['height' => 400, 'width' => 700],
    ],
  ];
Impacts: 
Module developers
Themers

Comments

joshi.rohit100’s picture

For all :- Don't forget to attach the library 'core/drupal.dialog.ajax', otherwise it will not work as it did for me ):

jonhattan’s picture

'data-accepts' => 'application/vnd.drupal-modal', was changed to 'data-dialog-type' => 'modal',. See Modal/dialog/ajax is using query parameters instead of accept headers.

norman.lol’s picture

Currently the 4th example (Open buttons/form action element in modal dialog) doesn't work anymore.

bloke_zero’s picture

Works if you add $this in form definition
'callback' => [$this, 'ajax_submit_order'],

sumanthkumarc’s picture

For example if a normal form shown on modal using modal api attributes set to link, the validation errors takes us back to normal page of form instead of on modal.

ndewany’s picture

When I run the example above, I get a textarea containing json instead of dialog.
Even I've already attach the library "core/drupal.dialog.ajax".

Any help ?

Thanks in advance

mtalt’s picture

I am also experiencing this same behavior where I see a textarea containing JSON. Did you ever find a fix for this?

liquidcms’s picture

I have a page with numerous modal links on it. I use a small jq script to "drag/select" some of these links. On mouseup of my select, my script does a .click() of the first link. This works great and opens up the modal (a node edit form). My question is asking if possible to pass information (the number of links selected) to the form being opened in the modal.

I naively tried to modify the link by adding the count to the end of the href. But this is not recognized by the .click() function.

anybody’s picture

Is there any command to open a modal with a route (or path) to be loaded, like with use-ajax instead of content?

I couldn't find a way yet. In my case modal should open, loading a route content, when clicking something in a form.

Something like:

$response->addCommand(new OpenRouteInModalDialogCommand($path, ['width' => '700']));

If there is, we should add it to the documentation and code examples!

http://www.DROWL.de || Professionelle Drupal Lösungen aus Ostwestfalen-Lippe (OWL)
http://www.webks.de || webks: websolutions kept simple - Webbasierte Lösungen die einfach überzeugen!
http://www.drupal-theming.com || Individuelle Responsive Themes