Рейтинг:0

How to close a modal with a submit form and implement a CloseModalDialogCommand?

флаг cn

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.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.