web-dev-qa-db-ja.com

フォーム送信後にモーダルを閉じる方法は?

エンティティ参照ウィジェットを作成しています。これは、入力フィールドの横に、ターゲットエンティティの編集フォームへの参照リンクを表示します。リンクに次の属性を設定して、モーダルで開くようにします。

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

それは完璧に動作します。しかし、モーダルフォームで[送信]をクリックすると、モーダルが閉じられてこのウィジェットが使用されている元のフォームにとどまる代わりに、参照されているエンティティビューページにリダイレクトされました。

元のビューにリダイレクトする代わりにモーダルフォームの送信ボタンにモーダルを閉じるように指示する特別な属性( "data-dialog-type"など)はありますか?

[〜#〜]更新[〜#〜]

これをURLに追加すると、実際にはほとんど問題が解決します。

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

これにより、が元のページにリダイレクトされ、潜在的な値が更新されます(参照されているアイテムのタイトル)。これは実際にはかなり良いことです!

そうは言っても、私はまだ「ajax submit」バージョンに興味があります!

3
ssibal

独自のEntityEditFormを実装して使用する必要があります-これは事実ですか?次に、最後のコードブロックにスキップします:D

それ以外の場合は、最初にこれを実行する必要があります。カスタムフォームを「挿入」する方法については、この回答( alterrouteによるエンティティの追加/編集フォームのオーバーライド )を参照してください。ここで重要なコード(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 {}

そこで、次のように#ajaxが設定されていることを確認します。

<?php

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

そしてajaxSubmit関数を上書きして、次のように CloseModalDialogCommand を追加します。

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

カスタムモジュールでイベントサブスクライバーのみを使用してこれを解決しました。

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'],
    ];
  }

}

これは、レイアウトビルダーでブロックを作成した後、モーダルを閉じます。

2
Kllrthr