Ajax Dialog Boxes

Last updated on
12 March 2024

This documentation needs work. See "Help improve this page" in the sidebar.

Overview

Dialogs are often referred to as dialog boxes, modal windows, or pop-up windows. Whatever you call them, they are a quick and easy way to display additional information without having to reload the entire page. Dialog boxes can display just some static text, any node or form of your page, a views page, or any custom markup you'll feed to them.  

Drupal core offers different types of dialogs:

  • Modal dialogs
  • Non modal dialogs
  • Off canvas dialogs

There are many ways to display a dialog box in Drupal, depending on your use case. The simplest way to show a dialog box is by simply adding the "use-ajax" class to an HTML anchor tag. Dialogs can also be displayed using AJAX Callback Commands like OpenModalDialogCommand or OpenOffCanvasDialogCommand

Types of Dialogs

Drupal core offers three different types of dialog boxes that can be displayed without having to reload the entire page:

  • Modal dialogs: They overlap the entire page, no other elements can be clicked while modal dialogs are visible. Only one modal popup can be opened at the same time.
     
  • Non modal dialogs: They pop up and stay on top of the page, but still other elements on the page can be clicked. Multiple dialogs can be displayed at the same time.
     
  • Off canvas dialogs: Are no popup windows that overlap other content, but are sliding into the page by moving other content to the side. This type of dialog is especially useful to display larger portions of content, like long detail pages that could require the user to scroll down. Also, the off-canvas dialog is well usable on mobile devices. 
     

Types of Drupal dialog boxes

Prerequisites

Before you try to display dialogs on your site, make sure the drupal.dialog.ajax library is loaded. Add the library as a dependency to your theme or module. 

Here is my example module's mymodule.libraries.yml

mymodule:
  version: 1.x
  css:
    theme:
      css/mymodule.css: {}
  js:
    js/mymodule.js: {}
  dependencies:    
    - core/jquery #Just to be safe
    - core/drupal.dialog.ajax #Required for dialogs
    - core/jquery.form #If you also want to use Ajax for form operations

and in my mymodule.module file

function mymodule_preprocess_node__page(array &$variables) : void {
	//Module name: 'mymodule', library name: 'mymodule'. 
	$variables['#attached']['library'][] = 'mymodule/mymodule';
}

See Adding stylesheets (CSS) and JavaScript (JS) to a Drupal 8 theme for details about how to add libraries.

Note: the core/jquery.form library was deprecated in Drupal 9.4 and removed in 10.0. Apparently this caused issues in some cases when the embedded form had an Ajax callback. However, when this callback returns and AjaxResponse, it does not appear to be needed.

Displaying dialogs in Drupal

Links can be used to display a dialog box by simply adding the use-ajax class to the HTML element and specifying some dialog options.

This link opens /node/1 in a modal dialog box:

<a class="use-ajax" 
    data-dialog-options="{&quot;width&quot;:400}" 
    data-dialog-type="modal" 
    href="/node/1">
    First node displayed in modal dialog.
</a>

{% set advanced_options = {
    "classes": {
      "ui-dialog": "my-custom-class"
    },
    "width": 400
} %}

<a class="use-ajax" 
    data-dialog-options="{{ advanced_options|json_encode() }}"    
    data-dialog-type="modal" 
    href="/node/1">
    Dialog with advanced options.
</a>

Available dialog parameters

  • data-dialog-type: This is either 'modal' or 'dialog'.
  • data-dialog-options: A JSON encoded string of options for Drupal.dialog. See http://api.jqueryui.com/dialog/ for all available options.
  • data-dialog-renderer: Allow dialog links to specify a renderer in addition to a dialog type. This is required if you want to display a off canvas dialog.

Some more parameters will be available for Ajaxified links from Drupal 8.9 on and allow content on your page to be dynamically altered using this simple use-ajax approach. A patch for 8.7+ can be found in this issue, more info and example code can be found in this change record.

  • data-ajax-wrapper: This accepts the ID of the HTML element (without the #) that should be replaced by the content fetched via AJAX. The AJAX system already supported setting the wrapper for Drupal.Ajax, this behavior has not been changed. Now AJAX links can also use this.
  • data-ajax-progress: By default, the AJAX links used the throbber progress indicator. AJAX links can now override the default with this data attribute (by setting this to 'fullscreen' for example).
  • data-ajax-focus: This accepts a jQuery selector targeting the element that should receive focus. By default, the focus is returned to the AJAX link after the AJAX request is handled. AJAX links can now override this default with this data attribute. This was added to improve accessibility.
  • data-ajax-http-method: The HTTP method to be used when opening the dialog. It defaults to POST. Note that setting to GET will benefit from caching.

Let's create a simple page with three links to another node that will be displayed each of the three Drupal Ajax dialog types.

Drupal Ajax Dialogs Example

In the example, the page makes sure to use the Full HTML text format and takes care of adding the Ajax dialog library. We're loading the page at /node/1 in this example but you could also simply create a Drupal Views page and use the URL of the view in your link instead of /node/1.

<p>Here are some nice articles. Click the title to display the article in a dialog box using an Ajax request.</p>

<ol>
	<li>
        <a class="use-ajax" 
            data-dialog-options="{&quot;width&quot;:400}" 
            data-dialog-type="modal" 
            href="/node/1">
            First article displayed in modal dialog.
        </a>
    </li>
	<li>
        <a class="use-ajax" 
            data-dialog-options="{&quot;width&quot;:400}" 
            data-dialog-type="dialog" 
            href="/node/1">Second article displayed in non modal dialog.
        </a>
    </li>
	<li>
        <a class="edit-button use-ajax" 
            data-dialog-options="{&quot;width&quot;:400}" 
            data-dialog-renderer="off_canvas" 
            data-dialog-type="dialog" 
            href="/node/1">
            Third article displayed in a nice off canvas dialog.
        </a>
    </li>
</ol>
<?php
$form['link'] = [
    '#type' => 'link',
    '#title' => 'Link 1 (modal)',
    '#url' => Url::fromRoute('ajax_test.dialog_contents'),
    '#ajax' => [
      'dialogType' => 'modal',
      'dialog' => ['height' => 400, 'width' => 700],
    ],
  ];

For more examples see change record Ajax commands for opening and closing dialogs.

Open dialog for javascript

If you want to open a dialog directly from javascript (without html link or PHP declaration), you could use this snippet:

var ajaxSettings = {
  url: '/node/1',
  dialogType: 'modal',
  dialog: { width: 400 },
};
var myAjaxObject = Drupal.ajax(ajaxSettings);
myAjaxObject.execute();

This scenario doesn't seems allow behaviours (to be confirmed).

Forms in Ajax dialogs

If the URL for the Ajax dialog link returns a form, its action buttons are shown at the bottom of the dialog. You should ensure that the form's buttons are returned by the actions() method. Cancel links need to have the following classes set to appear in the action area:

        '#attributes' => ['class' => ['button', 'dialog-cancel']],

Troubleshooting

Dialogs not displaying with a Javascript error

Double-check the way you're using data-dialog options. It should be a JSON encoded string of options for Drupal.dialog, which you might have to use &quot; instead of ". A valid parameter would be:

data-dialog-options="{&quot;width&quot;:400}" 

if your Ajaxified links just don't seem to open the href target links in a popup, even though you double-checked your markup, you might simply miss the required libraries.

Use your JavaScript inspector to see if the libraries are loaded:

Check if Drupal Ajax libraries are loaded

Once a modal link is on the page and has been processed by the Ajax JavaScript, changing the href of the link will not change the actual URL loaded into the modal window. To dynamically change the URL used by the modal, you must also:

  1. Unbind the existing "click" handler.
  2. Reset the "once" on your link.
  3. Call bindAjaxLinks() again to make the link use a modal.

Example code for changing a link with the ID "my-link":

$('#my-link')
  // Change the link href.
  .attr('href', '/my-new-url')
  // Unbind the old Ajax click handler.
  .unbind('click');
// Remove the once() so it will get processed again.
once.remove('ajax', '#my-link');
// Attach the Ajax action to this link.
Drupal.ajax.bindAjaxLinks(document.body);

Tags

Help improve this page

Page status: Needs work

You can: