Form API #ajax の利用方法

アイキャッチ画像 Umi->d

DrupalのForm APIで #ajaxというプロパティがありそれについてのご紹介をしたいと思います。

#ajaxプロパティとは

例えば、セレクトボックスの選択状態によって、別のセレクトボックスの選択値を切り替える場合
通常であればJavaScriptを実装し、表示内容を変更する対応を行うと思います。

Drupalの場合、この #ajax プロパティにコールバック関数を指定すると、DrupalがJavaScriptを生成し
バックエンドで指定したコールバック関数を実行することが可能になります。

既存フォームへの #ajax プロパティの実装例

今回は既存のノード編集フォームへ #ajax プロパティを追加してみます。
例として 都道府県 フィールドの内容によって 市区町村 フィールドの選択値を切り替えます。

モジュール構造

モジュールのファイル構成は以下の通りです

d842_form_ajax
├── d842_form_ajax.info.yml
└── d842_form_ajax.module

コンテンツタイプ(基本ページ)定義

基本ページコンテンツタイプに画像のように2つのフィールドを追加します。

  • 都道府県(field_pref)
  • 市区町村(field_city)

image1

タクソノミー(都道府県、市区町村)定義

ノード編集フォームで利用する為のタクソノミーを定義します。

  • 都道府県市区町村(pref_city)

都道府県毎に市区町村を指定する為、階層化しておきます。

image2

ノード編集フォーム(#ajax 実装前)

ajax 実装前は以下のように 都道府県 を変更しても 市区町村 は何も変わりません。

movie1

モジュール実装

都道府県フィールドの内容によって市区町村フィールドを変更したい為
処理のきっかけである都道府県フィールドに #ajax プロパティを追加します。

また、コールバック関数で市区町村フィールドの内容を更新する処理を実装します。

<?php

/**
 * @file
 * ノード編集フォームの特定のフィールドに#ajaxプロパティを追加.
 */

use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function d842_form_ajax_form_node_page_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // 都道府県フィールドにコールバック関数を追加.
  $form['field_pref']['widget']['#ajax'] = [
    'event' => 'change',
    'callback' => '_d842_form_ajax_set_city_callback',
    'wrapper' => 'edit-field-city-wrapper',
    'method' => 'replace',
  ];

  // 市区町村フィールドの選択値クリア.
  $form['field_city']['widget']['#options'] = ['_none' => '- なし -'];
}

/**
 * 都道府県フィールド変更時、市区町村フィールドを更新.
 *
 * @param array $form
 *   Form array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Form object.
 *
 * @return array
 *   市区町村フィールド定義.
 *
 * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
 */
function _d842_form_ajax_set_city_callback(array $form, FormStateInterface $form_state) {
  // 都道府県フィールドの内容取得.
  $pref_value = $form['field_pref']['widget']['#value'];
  // 市区町村フィールド情報取得.
  $field_city = $form['field_city'];
  // 複数回#ajaxが動くよう、IDを固定.
  $field_city['#id'] = 'edit-field-city-wrapper';

  // 都道府県未選択の場合、市区町村そのまま返却.
  if ($pref_value === '_none') {
    return $field_city;
  }

  // 市区町村の初期値.
  $options = ['_none' => '- なし -'];

  // Taxonomyから取得した都道府県に紐付く市区町村を取得.
  $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('pref_city');
  foreach ($terms as $term) {
    if ($term->parents[0] == $pref_value) {
      $options[$term->tid] = $term->name;
    }
  }
  // フィールドの選択値に取得した市区町村をセット.
  $field_city['widget']['#options'] = $options;
  // 初期値セット.
  $field_city['widget']['#value'] = '_none';

  return $field_city;
}

ノード編集フォーム(#ajax 実装後)

ajax 実装後は以下のように 都道府県 を変更すると 市区町村 も紐付いたものだけが選択できる状態になります。

movie2

まとめ

以上のようにForm APIの #ajax プロパティを利用すると選択項目によって動的に他のフィールドを変更することが可能になります。
バックエンドの値を取得する際、JavaScriptで実装するより短いコードで実装できますので、是非使ってみてください。

簡単ですが、Form APIの #ajax プロパティのご紹介でした。

コメントを追加

プレーンテキスト

  • HTMLタグは利用できません。
  • 行と段落は自動的に折り返されます。
  • ウェブページのアドレスとメールアドレスは自動的にリンクに変換されます。

Webプログラマー募集 私たちスタジオ・ウミは、共に技術を高め合い、共に価値ある仕事を追求できる仲間を探しています。