I saw this issue here, but I wanted to post this question as the answers seem incomplete and the question is not specific to closing a modal with a submit form.
In my .module
file, I am using a my_module_form_alter
and using ajax to open up a modal dialog:
$form['actions']['submit']['#ajax'] = [
'callback' => 'my_module_form_submit',
// prevent jump to top of page.
'disable-refocus' => TRUE,
'wrapper' => 'all_form',
'effect' => 'fade',
'progress' => [
'type' => 'throbber',
'message' => t('doing some work'),
],
];
$uses_modal = $config->get('use_modal');
if ($uses_modal) {
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
}
Then in the my_module_form_submit
function, I am opening the modal:
$title = $config->get('ajax_modal_title') ?: t('My Title!');
$content = \Drupal::formBuilder()->getForm('\Drupal\my_module\Form\AjaxModalForm');
$options = [
'width' => $config->get('ajax_modal_width'),
'height' => $config->get('ajax_modal_height'),
];
$uses_modal = $config->get('use_modal');
if ($uses_modal) {
$response->addCommand(new OpenModalDialogCommand($title, $content, $options));
}
return $response;
}
The $content
for the modal is getting a form I am building which has the close button form: $content = \Drupal::formBuilder()->getForm('\Drupal\my_module\Form\AjaxModalForm');
is pointing to a form I am building with a close button:
<?php
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\CloseModalDialogCommand;
class AjaxModalForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'ajax_modal_form';
}
public function buildForm(array $form, FormStateInterface $form_state) {
$form['actions'] = array('#type' => 'actions');
$form['actions']['cancel'] = [
'#type' => 'submit',
'#value' => $this->t('cancel'),
'#attributes' => [
'class' => [
'use-ajax',
],
],
'#ajax' => [
'callback' => '::closeModalForm',
'event' => 'click',
],
];
$form['#attached']['library'][] = 'core/drupal.dialog.ajax';
return $form;
}
public function closeModalForm(array $form, FormStateInterface $form_state) {
$command = new CloseModalDialogCommand();
$response = new AjaxResponse();
$response->addCommand($command);
return $response;
}
/**
* {@inheritDoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
This form displays in the modal pop up as expected. Debugging shows the form is getting built, but the callback doesn't fire to closeModalForm
. Also I get an ajax error when trying to close the button with the modal.
I have tried with no success:
- Taking the
::
out from before closeModalForm
in the callback.
- Changing the ajax array to
array(),
instead of [],
.
- Using
public static function
instead of public function
for the
closeModalForm
.
As another approach, I put something together using a Controller, which worked:
<?php
namespace Drupal\my_module\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\AjaxResponse;
class ModalController extends ControllerBase {
public function closeModalForm() {
$command = new CloseModalDialogCommand();
$response = new AjaxResponse();
$response->addCommand($command);
return $response;
}
}
And then called it like this in the $content
of the OpenModalDialogCommand
:
$content = [
'message' => [
'#markup' => t('some text'),
],
'close' => [
'#type' => 'container',
'#markup' => t('<a class=use-ajax href=":url">@close_text</a>', [
':url' => Url::fromRoute('my_module.closeModal')->toString(),
'@close_text' => $config->get('close_text') ?: t('Close'),
]),
],
];
I think using the controller is a little hacky if you don't have a page destination. It creates a link that can be opened in a new tab which is a white page with the dialog command in the corner.
So I want to know the cleanest way to get a submit form button to close the modal instead of a controller and link.