DrupalのAjax処理内で使用できるコマンドと、それを使ったフォームのバリデーションを紹介したいとおもいます
まずサンプルのフォームを作成します。
modules/custom
└── ajax_form
├── ajax_form.info.yml
├── ajax_form.routing.yml
└── src
└── Form
└── AjaxForm.php
ajax_form.info.yml
name: 'Ajax Form'
type: 'module'
description: 'Ajax Form'
core: '8.x'
ajax_form.routing.yml
ajax_form.form:
path: '/ajax-form'
defaults:
_form: '\Drupal\ajax_form\Form\AjaxForm'
_title: 'Ajax Form'
requirements:
_permission: 'access content'
AjaxForm.php
<?php
namespace Drupal\ajax_form\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Ajax Form.
*/
class AjaxForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'ajax_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form['sample'] = [
'#type' => 'textfield',
'#title' => 'sample',
];
$form['ajax'] = [
'#type' => 'submit',
'#value' => 'ajax',
'#ajax' => [
'callback' => [$this, 'validateAjax'],
'event' => 'click',
'progress' => [],
],
'#suffix' => '<span id="ajax-validate-message"></span>'
];
return $form;
}
/**
* {@inheritdoc}
*/
public function validateAjax(array &$form, FormStateInterface $form_state) {
$sample = $form_state->getValue('sample');
if (empty($sample)) {
$form_state->setErrorByName('sample', 'invalid value');
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
return $form;
}
}
本来フォームのバリデーションは validateForm
メソッドで行われますが、
Ajaxを使用する場合、callback
に指定されたメソッド(validateAjax
)で行います。そして
/**
* {@inheritdoc}
*/
public function validateAjax(array &$form, FormStateInterface $form_state) {
$sample = $form_state->getValue('sample');
if (empty($sample)) {
$form_state->setErrorByName('sample', 'value is empty.');
}
}
と実装したいところですが、Ajaxを使用すると、この setErrorByName
は動作しません。代わりにこのように実装します
namespace Drupal\ajax_form\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
+ use Drupal\Core\Ajax\AjaxResponse;
+ use Drupal\Core\Ajax\HtmlCommand;
/**
* Ajax Form.
*/
class AjaxForm extends FormBase {
/**
* {@inheritdoc}
*/
public function validateAjax(array &$form, FormStateInterface $form_state) {
$sample = $form_state->getValue('sample');
if (empty($sample)) {
$message = 'value is empty.';
}
else {
$message = 'success.';
}
$response = new AjaxResponse();
$response->addCommand(
new HtmlCommand('#ajax-validate-message', $message)
);
return $response;
}
この実装で、sampleに何も入力せずにajax
をクリックすると、下の画像のようになり、意図したバリデーションが効いていることが確認できます。
追加したコードを1つずつ見ていきましょう。 まずAjax レスポンス用インスタンスを生成します
$response = new AjaxResponse();
HtmlCommand
はjQueryのhtml()
メソッドを使用して、指定した要素内のテキストを、指定した文字列に変更することができます。
$response->addCommand(
new HtmlCommand('#ajax-validate-message', $message)
);
このコマンドの種類は他にもたくさんあるので、いくつか紹介したいと思います。
InvokeCommand
jQueryの任意のメソッドを使用することができます。
例)sampleフォームにerror
クラスを追加します
$response->addCommand(
new InvokeCommand('#edit-sample', 'addClass', ['error'])
);
CssCommand
jQueryのcss
メソッドを使用することができます
例)バリデートメッセージにcolor: red;
を適用します
$response->addCommand(
new CssCommand('#ajax-validate-message', ['color' => 'red'])
);
ReplaceCommand
jQueryのreplace
メソッドを呼び出し、第1引数で指定された要素を、第2引数で指定した要素に入れ替えます。
例)#ajax-validate-message
要素を<div>replaced</div>
に入れ替えます
$element = array(
'#type' => 'markup',
'#markup' => 'replaced',
'#prefix' => '<div>',
'#suffix' => '</div>',
);
$response->addCommand(
new ReplaceCommand('#ajax-validate-message', $element)
);
他にもモーダルを表示するコマンドなどあるので、下記のリンクを参考に実装してみてください! https://api.drupal.org/api/drupal/core%21core.api.php/group/ajax/8.6.x
募集しています
スタジオ・ウミは「Drupal」に特化したサービスを提供する Drupal のエキスパートチーム。
フルリモート&フレックス制だから、働く場所を選ばず時間の使い方も自由です。
そんなワークライフバランスの整った環境で、当ブログに書かれているような
様々な技術を共に学びながら、Drupalサイト開発に携わってみたい方を募集しています。
まずはお話だけでも大歓迎!ぜひお気軽にご連絡ください。