既存のフォームを変更する


12

Drupal 8から始めてすぐに、最初の問題にぶつかりました。

Drupal 8の既存のフォームを変更するにはどうすればよいですか?

ノードフォームのsaveメソッドを変更して、他のページにリダイレクトする必要があります。ノードフォームを変更して、マルチステップフォームのようなものにしたいと思います。ユーザーは新しいコンテンツを作成した後、新しいフォーム(作成した)にリダイレクトされ、さらに情報を取得します。

実装の問題を解決しましたhook_entity_type_alter()

function mymodule_entity_type_alter(&$entity_info) {
  $handlers = $entity_info['node']->get('handlers');
  $handlers['form']['default'] =    'Drupal\mymodule\Form\MyExtendedNodeForm';
  $handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
  $entity_info['node']->set('handlers', $handlers);
}

次に、ノードフォームを拡張し、saveメソッドを変更する新しいフォームクラスを作成しました。

class MyExtendedNodeForm extends NodeForm {

    public function save(array $form, FormStateInterface $form_state) {
      parent::save($form, $form_state);
      $node = $this->entity;
      $form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
  }

}

これは完全に機能しますが、それは良いですか?別のモジュールが同じことを行うと、コードは実行されなくなります。


2
Drupal 8はまだサポートしていますhook_form_alter()。フォームをリダイレクトする必要がある場合は、リダイレクトを行うフォーム送信ハンドラーを追加するだけで十分です。
kiamlaluno

@kiamlalunoそれは私が思う答えであるはずです:)
ベルディール

@Berdirそれだけではあまり役に立たないでしょう、私は怖いです:Drupal 8の私の知識はかなり限られています。さらに、OPは「save()メソッドを変更する」が実際に何を意味するのかを明確にする必要があります。データの保存方法を変更するのですか、それとも単にリダイレクトするのですか?前者の場合、答えはより複雑です。
kiamlaluno

@kiamlaluno Thxの回答。この場合、save()の後にリダイレクトを行うだけでよいので、答えは機能します。しかし、私はまた、Drupal 8の正しい方法でフォームの他の要素を変更する方法にも興味がありました。たとえば、保存方法を変更したり、フォームにフィールドを追加したりします。など
Jens Steppe

回答:


4

昨日まったく同じことをしなければならなかったので、これを行うためのDrupal 8の方法をまだ探していますが、見つかりませんでした。私はこのようにしてやった:

<?php

/**
 * @file
 * This is my module.
 */

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Implements hook_form_alter().
 */
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['actions']['submit']['#submit'][] = '_MODULE_goto';
  }
}

/**
 * Make the form go to route.id.
 */
function _MODULE_goto($form, FormStateInterface $form_state) {
  $form_state->setRedirect('route.id');
}

私はまだ別の方法でそれを行うことに非常に興味があります、私のモジュールは.moduleファイルなしでとてもきれいに見えました:)。


3

Drupal 8.1.1を使用していて、ユーザーがアカウントを変更した後、/ user / editページの[保存]ボタンをクリックした後にユーザーをリダイレクトしようとしました。私は最初にこれを試しました:

/**
 * Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['#submit'][] = '_MODULE_goto';
  }
}

それはうまくいきましたがuser_login_form、うまくいきませんでしたuser_form。以下のためにuser_form私が使用していました

$form['actions']['submit']['#submit'][] = '_MODULE_goto';

同じ問題に遭遇した他の人の助けになることを願っています!


1

site_information_settingsフォームを変更してフィールドを追加したかったのです。

あなたと同じように、

  • hook_form_alter(またはhook_form_FORM_ID_alter
  • 元のフォームクラスを拡張する

OOPを作成したかったので、system.site_information_settingsルートの_form属性を変更するルートサブスクライバーサービスの作成を開始しました。

次にSiteInformationForm、フィールドを拡張する新しいクラスで、フィールドとそのバリデーターが追加され、送信関数が拡張された後、あなたとまったく同じように感じました... 別のモジュールがフォームのルートを書き換えて独自のクラスを使用するとどうなりますか?

最初に戻ると、2つのオプションから選択できました...間違ったオプションを選択したようです。

hook_form_alter/ hook_form_FORM_ID_alter既存のフォームを変更する最良の方法のようです。


0

あなたがしたいことのように見えますが、実際にはsaveメソッドを変更するのではなく、ノードが保存されたときにリダイレクトを変更します。

この状況では、Drupal 7と同様にhook_form_alter、カスタム送信ハンドラー(フォームと要件に応じて、フォームまたはボタン上で)を実行するのが適切なソリューションです。

あなたが質問で説明することも機能しますが、実際にクラス内の何かを変更したくない限り、基本クラスを上書きすることは避けます。

いずれにしても、saveメソッドは送信ハンドラとして使用されるだけなので、リダイレクトを追加するためだけに上書きするのはあまり意味がありません。


0

より良い方法は、まだform_alterファミリーのフックの1つを使用し、送信ハンドラを接続し、その中でリダイレクトを設定することだと思います。

私の意見では、これを行うために基底クラスを拡張することは困難です。特に、機能は変更されていないため、リダイレクトのみです。


0

KernelEvents :: REQUESTイベントをリッスンする新しいEventSubscriberを作成し、ノードフォームを送信するときに反応することができます。 、これを

とにかくhook_form_alterの方法は大丈夫です。


0

私がこれまで見つけたもの:フォーム変更フックを実装し、フォーム変更フック自体で検証/送信ハンドラを変更しようとすると、$ form ['#validate] / $ form [#submit']ハンドラを変更した場合にのみ機能します。(このためにform_state関数を呼び出すと、フォーム変更フック自体で機能しません)

ただし、検証ハンドラー内でこれを試すと、動作する傾向があります。

// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();

// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
  unset($submit_handlers[$key_core_submit]);
  // Add your own submit handler.
  array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);

これは、フォーム変更フック自体の場合ではなく、フォームが完全に構築されたためです。

アイデアは、検証ハンドラーを最後のハンドラーとして追加し、送信用に存在する他のハンドラーを評価して、すぐに変更できるということです。

検証ハンドラも変更する場合は、他のハンドラよりも前に実行することを確認し、検証ハンドラで必要なものを変更します。

自分でもっと良い方法を探しているのですが、ユーザー登録フォームの検証/送信ハンドラを常に交換する必要があります。しかし、私のモジュールの実装を壊す他のモジュールが存在する可能性があります。したがって、私のモジュールはこれらをチェックできる必要があり、それはこの方法で可能です。これを実現するために、ビルド関数の後に何らかのエンティティフォームが存在するのではないかと思います。(フォームが完成して配信されようとしているときに実行されるもの)(この単純なケースでは複雑になりません)

save()メソッドのリダイレクトをバイパスすることはできませんが、save()の設定解除はこの方法で行います(+独自の実装)。確かに、クラスはより優れており、オブジェクトなどに簡単にアクセスできますが、コアクラスをオーバーライドすると、他のモジュールがこれらを使用するときに実際に問題が発生します。このコードを使用する場合はそうではありません。


0

この問題を確認した後、これはあなたのケースに合うはずであることがわかったものです:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.