On this page
Ajax Dialog Boxes
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.
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
Ajax Links
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="{"width":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.
Drupal Ajax Link example
Let's create a simple page with three links to another node that will be displayed each of the three Drupal Ajax dialog types.
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="{"width":400}"
data-dialog-type="modal"
href="/node/1">
First article displayed in modal dialog.
</a>
</li>
<li>
<a class="use-ajax"
data-dialog-options="{"width":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="{"width":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>
Link to a modal in a render array
<?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 "
instead of "
. A valid parameter would be:
data-dialog-options="{"width":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:
Changing the href of an existing modal link
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:
- Unbind the existing "click" handler.
- Reset the "once" on your link.
- 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);
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion