web-dev-qa-db-fra.com

Comment fermer le modal après l'envoi du formulaire?

Je crée un widget de référence d'entité, qui affiche le lien de référence, à côté du champ de saisie, vers le formulaire d'édition de l'entité cible. Je le fais s'ouvrir dans un modal, avec les attributs suivants sur le lien:

 'class' => ['use-ajax'],
          'data-dialog-type' => 'modal',
          'data-dialog-options' => json_encode([
            'height' => 700,
            'width' => 900,
          ]),

Cela fonctionne parfaitement. Cependant, lorsque je clique sur Soumettre sur le formulaire modal, je suis redirigé vers la page de visualisation de l'entité référencée, au lieu de fermer le modal et de rester sur le formulaire d'origine, où ce widget est utilisé.

Existe-t-il des attributs spéciaux (comme "type de boîte de dialogue de données") qui indiquent au bouton d'envoi du formulaire modal de fermer le modal au lieu de rediriger vers la vue d'origine?

[~ # ~] mise à jour [~ # ~]

L'ajout de cela à l'URL résout en fait à peu près le problème:

    'query' => [
      'destination' => $this->requestStack->getCurrentRequest()->getRequestUri(),
    ],

Cela redirige le vers la page d'origine, avec les valeurs potentielles mises à jour (titre d'élément référencé), ce qui est en fait une très bonne chose!

Cela étant dit, je suis toujours intéressé par la version "ajax submit"!

3
ssibal

Vous devez implémenter et utiliser votre propre EntityEditForm - est-ce le cas? Passez ensuite au dernier bloc de code: D

Sinon, vous devrez d'abord accomplir cela. Voir cette réponse ( remplacement d'un formulaire d'ajout/modification d'entité via alterroute ) pour une approche pour "injecter" un formulaire personnalisé. Voici le code crucial (adapté à NodeForm):

modules/custom/form_overwrite/form_overwrite.services.yml

services:
    route_subscriber:
        class: Drupal\form_overwrite\Routing\RouteSubscriber
        tags: 
 - {name: event_subscriber }

modules/custom/form_overwrite/src/Routing/RouteSubscriber.php

 <?php

/**
 * @file
 * Contains \Drupal\form_overwrite\Routing\RouteSubscriber.
 */

namespace Drupal\form_overwrite\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
     if ($route = $collection->get('entity.node.edit_form')) {
  $route->setDefault('_entity_form', '\Drupal\form_overwrite\Form\NewEditForm');
     }

   }
}

modules/custom/form_overwrite/src/Form/NewEditForm.php

<?php

namespace Drupal\form_overwrite\Form;

use Drupal\node\NodeForm;


/**
 * Form handler for the node edit forms.
 */
class NewEditForm extends NodeForm {}

Là, vous vous assurez que le #ajax est défini, comme:

<?php

public function form(array $form, FormStateInterface $form_state) {
   ...
   $form['actions']['DESIRED_EXISTING_ACTION'] = array(
      ...
      '#type' => 'submit',
      '#ajax' => array(
        'callback' => '::ajaxSubmit',
        'event' => 'click',
      ),
      ...
    );
   ...
}

et écraser la fonction ajaxSubmit, en ajoutant CloseModalDialogCommand , comme:

public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    if ($form_state->getErrors()) {
      ...
    }
    else {
      ...
      $response->addCommand(new \Drupal\Core\Ajax\CloseModalDialogCommand\CloseModalDialogCommand());
    }

    return $response;
  }
4
rémy

J'ai résolu ce problème en utilisant uniquement un abonné aux événements dans un module personnalisé.

modalCloseSubscriber.php

<?php

namespace Drupal\custom_module\EventSubscriber;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Custom module event subscriber.
 */
class ModalCloseSubscriber implements EventSubscriberInterface {

  /**
   * Current logged in user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Constructs event subscriber.
   *
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   Current logged in user.
   */
  public function __construct(AccountProxyInterface $current_user) {
    $this->currentUser = $current_user;
  }

  /**
   * Kernel response event handler.
   *
   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
   *   Response event.
   */
  public function onKernelResponse(FilterResponseEvent $event) {
    $response = $event->getResponse();
    if (!$response instanceof AjaxResponse) {
      return;
    }
    if ($response->getCommands()) {
      $commands = $response->getCommands();
      if (empty($commands)) {
        return;
      }
      elseif (!empty($commands)) {
        foreach ($commands as $command) {
          if ($command['command'] == 'insert' && $command['selector'] == '#layout-builder') {
            // leave blank for default modal window to close.
            $response->addCommand(new CloseDialogCommand());
          }
        }
      }
    }

  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      KernelEvents::RESPONSE => ['onKernelResponse'],
    ];
  }

}

Cela ferme le modal après avoir créé un bloc avec le constructeur de mise en page.

2
Kllrthr