web-dev-qa-db-ja.com

カスタムテンプレートを使用したカスタムフォーム、フォームの送信は検証および送信ハンドラーを呼び出さない

カスタムテンプレートフォームを使用してクラスフォームを作成する単純なカスタムモジュールを作成しました。カスタムテンプレートを使用しない場合(.moduleの_themeフックにコメントを付ける)、フォームを送信すると、クラスメソッドハンドラーの検証と送信が呼び出されます。しかし、カスタムフォームテンプレートを使用しているときに、フォームを送信し、クラスメソッドの検証と送信のハンドラーが呼び出されない場合、その理由がわかりません。

これは私のコードです。私は私のtemplates/form--myformtest-form.html.twigテンプレートから始めます。

<h1>TEST</h1>
<form{{ element }}></form>

Myformtest.moduleコードは次のとおりです。

/**
 * Implements hook_theme().
 */
function myformtest_theme($existing, $type, $theme, $path)
{
  return array(
    'form__myformtest_form' => array(
      'render element' => 'form',
      'template' => 'form--myformtest-form',
    ),
  );
}

このフックにコメントを付けると、フォームはデフォルトのテーマフォームテンプレートを使用します。この場合、フォームコールを送信し、validateおよびsubmitクラスハンドラーメソッドを送信します。このフックにコメントしない場合、フォームはカスタムテンプレートを使用します。次に、カスタムフォームページにアクセスしてフォームを有効にすると、validateおよびsubmitハンドラーが呼び出されません。

これは、私のsrc/Form/MyformtestForm.phpクラスの単純なコードです。

class MyformtestForm extends FormBase {
  //...
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['textfieldtest'] = [
      '#type' => 'textfield',
      '#title' => $this->t('textfieldtest'),
      '#maxlength' => 64,
      '#size' => 64,
    ];

    $form['submit'] = [
        '#type' => 'submit',
        '#value' => t('Submit'),
    ];

    return $form;
  }

  public function validateForm(array &$form, FormStateInterface $form_state) {
    ksm("MyformtestForm Validate handler!");
    // logs never displayed when I use my custom template. If I don't use the custom template, this log appears.
  }

  public function submitForm(array &$form, FormStateInterface $form_state) {
    ksm("MyformtestForm Submit handler");
    // logs never displayed when I use my custom template. If I don't use the custom template, this log appears.
  }

フォームでカスタムオーバーライドを使用しているときにハンドラーが呼び出されないのはなぜですか?どうすれば電話できますか?

これらは、フォームページを読み込むときにカスタムテンプレートから存在する変数です。

screenshot

3
matthieu lopez

そこに「ベースフック」が必要だと思います。

次に例を示します。

/**
 * Implements hook_theme().
 */
function formcustomtemplate_theme() {
  return array(
    'form__my_form_test' => array(
      'render element' => 'form',
      'template' => 'form--myformtest-form',
      'base hook' => 'form',
    ),
  );
}

カスタムテーマを使用していて、モジュールにテンプレートが必要ない場合は、カスタムフォームに新しいテーマフックを作成するアプローチは不要です。
新しいテーマフックを作成するのではなく、テーマでhook_theme_suggestions_alterを使用します。

/**
 * Implements hook_theme_suggestions_alter().
 */
function mytheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {

  if ($hook == 'form' & !empty($variables['element']['#theme'])) {
    $suggestions[] = 'form__' . $variables['element']['#theme'][0];
  }

}

次に、テーマに適切なテンプレートを作成します。

次に、ページに出力されるテーマ提案を表示するには、twigデバッグをオンにします。

https://drupalize.me/blog/201405/lets-debug-twig-drupal-8

マークアップにテンプレートの提案が表示されます。

<!-- FILE NAME SUGGESTIONS:
   * form--myformtest-form.html.twig
   x form.html.twig
-->

テンプレートをまだ取得していないことがわかるので、form.html.twigをコピーして名前を変更して、テンプレートファイルを作成します。

Drupalが "form"フックを使用してテンプレートを探している場所を確認するには、hook_theme_registry_alterからテーマレジストリを印刷します。

 "form" => array:6 [▼
    "template" => "form"
    "path" => "themes/custom/mycustomtheme/templates/form"
    "type" => "theme_engine"
    "theme path" => "themes/custom/mycustomtheme”
    "render element" => "element"
    "preprocess functions" => array:4 [ …4]

これにより、テンプレートをそのディレクトリに配置する必要があることがわかります。

3
oknate

これは、フォームの各要素のスタイルを設定したい人にとって役立つかもしれません。

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */

function MODULE_NAME_form_YOUR_FORM_ID_alter(&$form, FormStateInterface &$form_state) {
  $form['#theme'] = ['CUSTOM_NAME'];
}

その後、必要な要素でフックを設定しました。

/**
 * Implements hook_theme().
 */
function MODULE_NAME_theme($existing, $type, $theme, $path) {
  return [
    'CUSTOM_NAME' => [
      'render element' => 'form',
    ],
  ];
}

私はそれに応じてテンプレートに名前を付けました(CUSTOM_NAME.html.twig)。ここでは、$form要素(例:{{ form.name }}、 から来る $form['name'])。

そして最後に、BELIEVE ME、特に、そして最も重要なこととして、form_build_idおよびform_token変数を含めることを忘れないでください。

  {{ form.form_build_id }} {# required #}
  {{ form.form_id }} {# required #}
  {{ form.form_token }} {# required #}

質問への答えはすでに選択されています。これは、フォームをより徹底的にテーマ化する方法の説明を取得するだけの簡単なものです。

乾杯

1

drupal 7で作業した場合、 drupal 7でレンダリングdrupal_render_children($form); drupal render隠しフィールドとcsrfフィールド From.html.twigによると

利用可能な変数

attributes: A list of HTML attributes for the wrapper element.
children: The child elements of the form.

最初に要素を希望どおりにレンダリングしたい場合は、最後に{{ children}}をdrupal 7メソッドとしてレンダリングする必要があります。

だから最初に欲望の要素をレンダリングし、次に{{ children }}をレンダリングします。

<h1>TEST</h1>
<div class="myclass">{{ element }} </div>
// other elements
// and finally
{{ children }}
0
Yusef

あなたのフォームのレンダリングも問題だと思います。 form.html.twigのようなコアのデフォルトのフォームテンプレートを見てください。

https://api.drupal.org/api/drupal/core!modules!system!templates!form.html.twig/8.2.x

その方法で試して{{子}}を使用するか、{{element.textfieldtest}}のようなものを使用してフィールドを段階的にレンダリングしてください。

だから私はこのコードを使います

<h1>TEST</h1>
<form{{ attributes }}>
  {{ children }}
</form>

{{ dump }}を使用してテンプレートの出力をダンプし、どの変数があるかを確認することもできます。 twigデバッグを有効にするためのリンク https://www.drupal.org/docs/8/theming/twig/debugging-twig-templates

0
Chris4783