エンティティ参照ウィジェットを作成しています。これは、入力フィールドの横に、ターゲットエンティティの編集フォームへの参照リンクを表示します。リンクに次の属性を設定して、モーダルで開くようにします。
'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」バージョンに興味があります!
独自の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;
}
カスタムモジュールでイベントサブスクライバーのみを使用してこれを解決しました。
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'],
];
}
}
これは、レイアウトビルダーでブロックを作成した後、モーダルを閉じます。