Skip to main content

Display Forms in a Modal Dialog with Drupal 8

Drupal 8 has a great AJAX Form API which includes some tools to create modal dialogs using the jQuery modal library. The Examples module even demonstrates how to create a custom form and display it in a modal window. But what if what you want to do is display an already created form in a modal? How do we do that? Let's see how to do it with an example. Let's display the node add form in a modal window.

The first thing that we need to do is create a link which will trigger the modal when the user clicks it. The only special things that this link needs to have are a few attributes that will let Drupal know to display the contents of the link in a dialog:

 
<a href="/node/add/article"
  class="use-ajax"
  data-dialog-type="modal"
  data-dialog-options="{'width':800,'height':500}">
    Create Node
</a>
 

Drupal also needs to include the JavaScript libraries which will read these attributes and make them work, so let's add the following libraries to your module's dependencies (in your equivalent to this example's modal_form_example.libraries.yml file).

  
  dependencies:
     'core/drupal.dialog.ajax',
     'core/jquery.form',
  

If you are unsure about how to add libraries on Drupal 8 you can consult the documentation to either add it in a theme or add it in a custom module. At the end of the post I will provide a repository with the code where I added the libraries in a block.

And that's it! If you click the link, the form will be displayed in a modal dialog! Drupal will automatically detect that you are sending an AJAX request and will display just the form so you won't need to worry about removing the rest of the blocks or hiding undesired markup.

The last thing missing, is what will happen if the user creates a node? By default, the node will redirect the user to another page but if we want to just close the modal dialog and leave the user on the same page we need to tell the form to do that. For this we are going to alter the form and add an AJAX command letting Drupal know that we want to close the dialog as soon as the node is created. In the .module file of a custom module we will add this code:

  
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;

/**
 * Implements hook_form_alter().
 */
function modal_form_example_form_node_article_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form['actions']['submit']['#submit'][] = '_modal_form_example_ajax_submit';
  $form['actions']['submit']['#attributes']['class'][] = 'use-ajax-submit';
}

/**
 * Close the Modal and redirect the user to the homepage.
 *
 * @param array $form
 *   The form that will be altered.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   FormState Object.
 */
function _modal_form_example_ajax_submit(array $form, FormStateInterface &$form_state) {
  $response = new AjaxResponse();
  $response->addCommand(new CloseModalDialogCommand());
  $form_state->setResponse($response);
}
 

The first function adds an extra submit function (which will be executed after Drupal finishes processing the node) and the second function adds the command to close the Dialog when the node has been created.

We can do this with practically any form in Drupal and you can add extra commands to do more complex things. Here are two resources:

More about...

Drupal 8, Drupal Planet, forms, and modal

Comments

2017 December 06
Bastien

Permalink

seems that your data-dialog

seems that your data-dialog-options are wrong, it's "{'width':800,';height':500}"> where it should be '{"width":800,"height":500}', otherwise it's not seen as an object but as a string and it crash on php side.

2017 December 07
David Valdez

Permalink

you are right.

I just fixed it, thanks!

2019 January 18
Joe Weirather

Permalink

In order to get this to work…

In order to get this to work, I had to add the following two lines to my form_alter:

$form['#attached']['library'][] = 'core/jquery.form';

$form['#attached']['library'][] = 'core/drupal.ajax';

Otherwise a GREAT tutorial, and working well for me, THANK YOU!

2019 March 12
Renaud

Permalink

Hello, I tried your module…

Hello, I tried your module in a more or less vanilla Drupal but It does not work. Here's what I see in the console. Any ideas what might be wrong ? Thanks for your help :)

TypeError: Argument 3 passed to Drupal\Core\Ajax\OpenModalDialogCommand::__construct() must be of the type array, string given, called in /Applications/MAMP/htdocs/mysite/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php on line 36 in Drupal\Core\Ajax\OpenModalDialogCommand->__construct() (line 33 of /Applications/MAMP/htdocs/rjsandbox/core/lib/Drupal/Core/Ajax/OpenModalDialogCommand.php) #0

2019 July 19
Changed

Permalink

Had to change data-dialog…

Had to change

data-dialog-options="{'width':800,'height':500}">

to

data-dialog-options="{&quot;width&quot;:800,&quot;height&quot;:500}">

otherwise php thought it was a string like the error above.

2019 August 23
Kent Shelley

Permalink

Thanks for the code!  A…

Thanks for the code!  A small modification I required was to run the dialog options through json encoder, like so.

'data-dialog-options' => Drupal\Component\Serialization\Json::encode(['width' => 600, 'height' => 400])

Using other methods I consistently got an Ajax error on dialog_options in Drupal\Core\Ajax\OpenModalDialogCommand

2019 September 05
Dominic

Permalink

I'm trying to do this for…

I'm trying to do this for the user register form which I open in a modal dialog from a custom action link.

The Ajax response doesn't work.  The commands (dialog close + refresh) I add in the submit function don't show up in the response in browser.  And, of course, the modal doesn't close and the page is not refreshed.

Any thoughts?

Thank you!

2019 September 05
Dominic

Permalink

My bad, I'm sorry... I was…

My bad, I'm sorry...

I was doing return $reponse; instead of $form_state->setResponse($response);

It does work! :)

2019 September 05
Clayton Dewey

Permalink

Hi Dominic, Glad to hear it…

Hi Dominic,

Glad to hear it works after all and that the blog post was useful for you!

2019 November 21
TD

Permalink

What is the path to open the…

What is the path to open the comment form? I mean the link to target the comment form

2019 December 05
Sandeep Prabhu

Permalink

This works fine for me. But…

This works fine for me. But pop modal popup not opening in IE 11. Getting error as below in console.

SCRIPT438: Object doesn't support property or method 'getAttributeNames'. 

 

Can anyone help me in solving this issue?

 

Thanks

2020 March 13
peter

Permalink

Thank you for your example…

Thank you for your example code for this. It is snippets like this that go a long way to getting D8 on track.

I have an autocomplete entity ref field on a bundle.. i want to add an "Add New" button there, which uses your code example to open an entity create form. On submit; it would need to add the newly created value to the existing autocomplete field. Would that be something one of the ajax core commands could do?

2020 June 27
peter

Permalink

Form doesn't validate. :(

Form doesn't validate. :(

2020 August 19
oss

Permalink

i'm also wondring of how i…

i'm also wondring of how i can do so with comment form? now i know the link and i can open it with the twig link but to validate the form it doesn't save or close the popup. i suppose it is because of the hook that it's work with the node entity and not with the comment.

can you tell me to how do so?

2021 September 08
AndrewMRiv

Permalink

To others getting the…

To others getting the following error, I have a solution.

TypeError: Argument 3 passed to Drupal\Core\Ajax\OpenModalDialogCommand::__construct() must be of the type array, string given, called in /Applications/MAMP/htdocs/mysite/core/lib/Drupal/Core/Render/MainContent/ModalRenderer.php on line 36 in Drupal\Core\Ajax\OpenModalDialogCommand->__construct() (line 33 of /Applications/MAMP/htdocs/rjsandbox/core/lib/Drupal/Core/Ajax/OpenModalDialogCommand.php) #0

Valid JSON is needed, so switch the single and double quotes from:

data-dialog-options="{'width':800,'height':500}"

to:

data-dialog-options='{"width":800,"height":500}'

I got the solution from this comment on drupal.org.

Add new comment

The content of this field is kept private and will not be shown publicly.

Markdown

The comment language code.
CAPTCHA Please help us focus on people and not spambots by answering this question.