やりたいこと
Form APIで作成したカスタムフォームのテンプレートをカスタマイズしたい
やり方
フォームを作成
まずは通常通りフォームとルートを作成する
Introduction to Form API
my_module/src/Form/MyForm.php
<?php
namespace Drupal\my_module\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Implements an example form.
*/
class ExampleForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'example_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['phone_number'] = [
'#type' => 'tel',
'#title' => $this->t('Your phone number'),
];
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Save'),
'#button_type' => 'primary',
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
if (strlen($form_state->getValue('phone_number')) < 3) {
$form_state->setErrorByName('phone_number', $this->t('The phone number is too short. Please enter a full phone number.'));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->messenger()->addStatus($this->t('Your phone number is @number', ['@number' => $form_state->getValue('phone_number')]));
}
}
my_module/my_module.routing.yml
example.form:
path: '/example-form'
defaults:
_title: 'Example form'
_form: '\Drupal\my_module\Form\ExampleForm'
requirements:
_permission: 'access content'
この時点でフォームにはデフォルトのテンプレートが適用されている
hook_themeにテーマの情報を登録
my_module/my_module.module
に以下のようにhook_theme
を書く。
/**
* Implements hook_theme().
*/
function my_module_theme($existing, $type, $theme, $path) {
return [
'example_form' => [ //テーマ名(任意)、テンプレート名になる
'render element' => 'form', // MyFormのbuildForm()で渡されてくるレンダリング配列のTwigの中での変数名(任意).
// 'template' => 'another-template-name', (テーマ名とテンプレート名が異なる場合はこちらで指定)
],
];
}
テンプレートの作成
my_module/templates/example-form.html.twig
を作成(テンプレート名はhook_theme
で指定したテーマ名と同じだが、ケバブケースにするように注意)
内容はとりあえずtestだけにしておく
test
フォームでテーマを指定
my_module/src/Form/MyForm.php
のbuildForm()
内のどこかに以下の一行を追加
$form['#theme'] = 'example_form';
フォームを確認
フォームにアクセスしてtest
が表示されていればOK
フォームをカスタマイズ
hook_theme
で設定したように、フォームの内容はform
という変数に入っているので、テンプレートを以下のようにすると完全なフォームが表示される。
{{ form }}
以下のように書くと特定のフォーム要素だけが取り出せる。
<div class="background-grey">{{ form.phone_number }}</div>
ただし全部のフォーム要素を並べても、フォームとしては機能しない。(送信ボタンを押しても何も起こらない)
<div class="background-grey">{{ form.phone_number }}</div>
{{ form.actions.submit }}
Twigのwithout
を使うとうまく機能するようになる。
<div class="background-grey">{{ form.phone_number }}</div>
{{ form|without('phone_number') }}