3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Drupal]カスタムフォームのテンプレートをカスタマイズする方法

Last updated at Posted at 2021-12-01

やりたいこと

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'

この時点でフォームにはデフォルトのテンプレートが適用されている
スクリーンショット 2021-12-01 19.24.09.png

スクリーンショット 2021-12-01 19.26.47.png

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.phpbuildForm()内のどこかに以下の一行を追加

$form['#theme'] = 'example_form'; 

フォームを確認

フォームにアクセスしてtestが表示されていればOK

スクリーンショット 2021-12-01 19.29.36.png

フォームをカスタマイズ

hook_themeで設定したように、フォームの内容はformという変数に入っているので、テンプレートを以下のようにすると完全なフォームが表示される。

{{ form }}

スクリーンショット 2021-12-01 19.32.16.png

以下のように書くと特定のフォーム要素だけが取り出せる。

<div class="background-grey">{{ form.phone_number }}</div>

スクリーンショット 2021-12-01 20.09.56.png

ただし全部のフォーム要素を並べても、フォームとしては機能しない。(送信ボタンを押しても何も起こらない)

<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') }}

スクリーンショット 2021-12-01 20.10.56.png

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?