メインコンテンツまでスキップ

JavaScript カスタマイズガイド

Form Plant はクライアント側 (JavaScript) でも柔軟に拡張できます。

  • カスタムバリデーション: コールバック API でフィールドごとの独自バリデーションを追加
  • ライフサイクルイベント: フォームの各ステップにカスタムイベントで処理を挿入
サーバー側との使い分け

JavaScript バリデーションはあくまで UX 向上 (即時フィードバック) のための仕組みです。セキュリティを伴う検証 (会社ドメイン制限、外部 API 連携など) は必ず PHP のバリデーションフック でも実装してください。JavaScript は DevTools 等で容易にバイパスできます。

対応範囲

埋め込み方式カスタムバリデーション APIライフサイクルイベント
固定ページ (ショートコード)対応対応
iframe 埋め込み非対応対応 (一部制限あり)
JavaScript 埋め込み非対応対応 (一部制限あり)

固定ページ上のフォームでは全機能が利用できます。iframe / JavaScript 埋め込みでは fplant:validateField イベントと fplant.addValidator() は利用できません。詳しくは末尾の制限事項を参照してください。


カスタム JS の読み込み方法

カスタム JS ファイルは wp_enqueue_script() で読み込み、fplant-form を依存に指定してください。

// functions.php またはプラグインファイル
function my_fplant_custom_scripts() {
wp_enqueue_script(
'my-fplant-custom',
get_stylesheet_directory_uri() . '/js/my-fplant-custom.js',
array( 'fplant-form' ), // form.js の後に読み込む
'1.0.0',
true
);
}
add_action( 'wp_enqueue_scripts', 'my_fplant_custom_scripts' );

fplant-form を依存に指定することで、window.fplant API が利用可能な状態でカスタム JS が実行されます。


カスタムバリデーション API

fplant.addValidator(fieldName, callback)

フィールドにカスタムバリデーターを登録します。

window.fplant.addValidator('email', function (value, fieldName, formData) {
// value: フィールドの現在値
// fieldName: フィールド名 (例: 'email')
// formData: 全フィールドのデータオブジェクト

if (value && !value.endsWith('@example.com')) {
return '@example.com ドメインのみ使用できます'; // エラーメッセージを返す
}
return ''; // 空文字列で検証成功
});

引数:

引数説明
fieldNamestring対象フィールドの name 属性値
callbackfunctionバリデーション関数

コールバック関数:

引数説明
valuestring / Array / File / nullフィールドの現在値 (下記参照)
fieldNamestringフィールド名
formDataobjectフォーム全体のデータ ({ fieldName: value, ... })

value のフィールドタイプ別の型:

フィールドタイプvalue の型内容
テキスト / メール / URL 等string入力値
テキストエリアstring入力値
チェックボックスstring[]チェックされた value の配列
ラジオボタンstring / null選択された value、未選択時は null
ファイルFile / null選択されたファイルオブジェクト、未選択時は null

戻り値:

  • エラーメッセージの文字列を返すとバリデーションエラーになります
  • 空文字列または falsy 値 ('', null, undefined) を返すと検証成功です

fplant.removeValidator(fieldName, callback)

登録済みのバリデーターを解除します。

// 特定のバリデーターを解除
var myValidator = function (value) { /* ... */ };
fplant.addValidator('email', myValidator);
fplant.removeValidator('email', myValidator);

// フィールドの全バリデーターを解除 (callback 省略)
fplant.removeValidator('email');

利用例: 複数フィールドの連動バリデーション

// パスワード確認フィールドの一致チェック
fplant.addValidator('password_confirm', function (value, fieldName, formData) {
if (value && formData.password && value !== formData.password) {
return 'パスワードが一致しません';
}
return '';
});

利用例: 条件付き必須チェック

// 「その他」を選択した場合のみ詳細入力を必須にする
fplant.addValidator('other_detail', function (value, fieldName, formData) {
if (formData.category === 'other' && (!value || value.trim() === '')) {
return '「その他」を選択した場合は詳細を入力してください';
}
return '';
});

利用例: 文字数制限

fplant.addValidator('message', function (value) {
if (value && value.length > 500) {
return 'メッセージは 500 文字以内で入力してください (現在: ' + value.length + ' 文字)';
}
return '';
});

ライフサイクルイベント一覧

フォームの各ステップで CustomEvent が発火します。form 要素 (.fplant-form) に対してリスナーを登録します。

フォーム初期化 ──── fplant:init

入力・バリデーション ── fplant:validateField (cancelable)

送信ボタン click

バリデーション
├── エラー時 ──── fplant:error

送信前 ──────────── fplant:beforeSubmit (cancelable)

ローディング ────── fplant:loading { loading: true }

確認画面表示 ────── fplant:confirmationShow
│ ├── 戻る ──── fplant:confirmationHide

最終送信

ローディング ────── fplant:loading { loading: false }

├── 成功 ──────── fplant:success
└── エラー ────── fplant:submitError

イベント一覧

イベント名cancelable発火タイミング
fplant:initfalseフォーム初期化完了時
fplant:validateFieldtrue各フィールドのバリデーション後 (エラーなし時)
fplant:beforeSubmittrueバリデーション成功後、送信処理の直前
fplant:errorfalseバリデーションエラー表示時
fplant:loadingfalseローディング状態の変化時
fplant:confirmationShowfalse確認画面の表示時
fplant:confirmationHidefalse確認画面から入力画面に戻った時
fplant:successfalseフォーム送信成功時
fplant:submitErrorfalseサーバー送信後のエラー時

cancelable イベントについて: cancelable: true のイベントでは e.preventDefault() を呼ぶことで処理を中断できます。


各イベントの詳細と利用例

fplant:init

フォームの初期化完了時に発火します。

プロパティ (detail)説明
formIdstringフォーム ID
formHTMLElementフォーム要素
document.addEventListener('fplant:init', function (e) {
console.log('フォーム #' + e.detail.formId + ' が初期化されました');

var form = e.detail.form;
form.querySelector('.my-custom-field')?.classList.add('initialized');
});

fplant:validateField

各フィールドのバリデーション後に発火します (組み込みバリデーション・カスタムバリデーターの両方でエラーがなかった場合のみ)。cancelable: true なので、preventDefault() で独自エラーを表示できます。

プロパティ (detail)説明
fieldNamestringフィールド名
valueanyフィールドの現在値
fieldHTMLElementフィールド要素
groupHTMLElementフィールドグループ要素
errorMessagestring / nullエラーメッセージ (リスナーから設定可能)

preventDefault() でカスタムエラーを表示する:

var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:validateField', function (e) {
if (e.detail.fieldName === 'email') {
var value = e.detail.value;
if (value && value.indexOf('@company.co.jp') === -1) {
e.detail.errorMessage = '社内メールアドレス (@company.co.jp) を使用してください';
e.preventDefault(); // バリデーションエラーにする
}
}
});
ポイント

e.detail.errorMessage にエラーメッセージを設定し、e.preventDefault() を呼んでください。両方が必要です。errorMessage を設定しない場合はデフォルトのエラーメッセージが表示されます。

addValidator() との使い分け:

  • addValidator() — シンプルなバリデーションに最適。コールバック関数を渡すだけ
  • fplant:validateField — DOM 要素へのアクセスが必要な場合や、複数フィールドの組み合わせで判定する場合に便利

fplant:beforeSubmit

バリデーション成功後、実際の送信処理の直前に発火します。cancelable: true なので、preventDefault() で送信を中止できます。

プロパティ (detail)説明
formIdstringフォーム ID
formDataobject送信されるフォームデータ
// GA4 でフォーム送信開始をトラッキング
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:beforeSubmit', function (e) {
gtag('event', 'form_submit_start', {
form_id: e.detail.formId,
});
});
// 送信前に確認ダイアログを表示
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:beforeSubmit', function (e) {
if (!confirm('この内容で送信してよろしいですか ?')) {
e.preventDefault(); // 送信を中止
}
});

fplant:error

バリデーションエラーが表示された時に発火します。

プロパティ (detail)説明
fieldErrorsobjectフィールド別エラーメッセージ ({ fieldName: 'エラー文', ... })
messagestringエラーの全体メッセージ
// エラー時のシェイクアニメーション
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:error', function (e) {
Object.keys(e.detail.fieldErrors).forEach(function (fieldName) {
var group = document.querySelector(
'.fplant-field-group[data-field-name="' + fieldName + '"]'
);
if (group) {
group.classList.add('shake');
setTimeout(function () { group.classList.remove('shake'); }, 600);
}
});
});
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-5px); }
40%, 80% { transform: translateX(5px); }
}
.shake {
animation: shake 0.6s ease;
}

fplant:loading

ローディング状態が変化した時に発火します。送信開始時 (true) と完了時 (false) の 2 回発火します。

プロパティ (detail)説明
loadingbooleantrue: ローディング開始、false: ローディング終了
// カスタムローディングオーバーレイ
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:loading', function (e) {
var overlay = document.getElementById('my-loading-overlay');
if (overlay) {
overlay.style.display = e.detail.loading ? 'flex' : 'none';
}
});

fplant:confirmationShow

確認画面が表示された時に発火します。

プロパティ (detail)説明
formIdstringフォーム ID
confirmationElHTMLElement確認画面の要素
// 確認画面のフェードインアニメーション
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:confirmationShow', function (e) {
var confirmation = e.detail.confirmationEl;
confirmation.style.opacity = '0';
confirmation.style.transition = 'opacity 0.3s ease';
requestAnimationFrame(function () {
confirmation.style.opacity = '1';
});
});
// 確認画面表示時にページ上部にスクロール
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:confirmationShow', function (e) {
window.scrollTo({ top: 0, behavior: 'smooth' });
});

fplant:confirmationHide

確認画面から入力画面に戻った時に発火します。

プロパティ (detail)説明
formIdstringフォーム ID
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:confirmationHide', function (e) {
form.style.opacity = '0';
form.style.transition = 'opacity 0.3s ease';
requestAnimationFrame(function () {
form.style.opacity = '1';
});
});

fplant:success

フォーム送信が成功した時に発火します。サーバーからのレスポンスデータがそのまま detail に含まれます。

プロパティ (detail)説明
action_typestring送信後アクション ('message' / 'redirect' / 'custom_page')
messagestring成功メッセージ
redirect_urlstringリダイレクト先 URL (action_type'redirect' の場合)
success_page_htmlstringカスタム完了画面 HTML (action_type'custom_page' の場合)
// GA4 でコンバージョントラッキング
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:success', function (e) {
gtag('event', 'form_submit_success', {
action_type: e.detail.action_type,
});
});
// 送信成功後にカスタム処理を実行
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:success', function (e) {
setTimeout(function () {
window.location.href = '/thank-you/';
}, 3000);
});

fplant:submitError

サーバーへの送信後にエラーが返された時に発火します。バリデーションエラー (fplant:error) とは異なり、サーバー通信後のエラーです。

プロパティ (detail)説明
messagestringエラーメッセージ
errorsobjectフィールド別エラー ({ fieldName: 'エラー文', ... })
var form = document.querySelector('.fplant-form');
form.addEventListener('fplant:submitError', function (e) {
console.error('フォーム送信エラー:', e.detail.message);

// Sentry 等に送信
if (typeof Sentry !== 'undefined') {
Sentry.captureMessage('Form submission error: ' + e.detail.message);
}
});

注意事項

JS バリデーションはセキュリティ対策ではない

JavaScript によるバリデーションは UX 改善 (即時フィードバック) が目的です。セキュリティ上の入力検証は PHP のバリデーションフック で行ってください。JavaScript は DevTools 等で容易にバイパスできるため、サーバーサイドバリデーションは常に独立して実行されます。

エラーメッセージは安全に処理される

カスタムバリデーターや fplant:validateField で設定したエラーメッセージは textContent で表示されます。HTML タグは解釈されずプレーンテキストとして表示されるため、XSS のリスクはありません。

バリデーターのエラーハンドリング

addValidator() で登録したコールバック関数内で例外が発生した場合、エラーは自動的に無視され、フォームの動作には影響しません。開発時のデバッグのため、コールバック内で適切なエラーハンドリングを行うことを推奨します。

イベントリスナーの登録タイミング

fplant:init を除くイベントリスナーは、フォームの DOM が存在すれば任意のタイミングで登録できます。DOMContentLoaded 後に登録するのが安全です。

document.addEventListener('DOMContentLoaded', function () {
var form = document.querySelector('.fplant-form');
if (form) {
form.addEventListener('fplant:beforeSubmit', function (e) {
// ...
});
}
});

複数フォームがある場合

同一ページに複数フォームがある場合、各フォーム要素に個別にリスナーを登録するか、e.detail.formId で対象フォームを判定してください。イベントは bubbles: true で発火するため、document レベルでもリッスンできます。

document.addEventListener('fplant:beforeSubmit', function (e) {
if (e.detail.formId === '145') {
// フォーム #145 の場合のみ処理
}
});

iframe / JavaScript 埋め込みでの制限

iframe 埋め込みおよび JavaScript 埋め込み (embed.js) では以下の制限があります。

  • fplant:validateField イベントは発火しません (クライアントサイドバリデーションがないため)
  • window.fplant.addValidator() / removeValidator() は利用できません
  • fplant:beforeSubmitdetail.formData は含まれません (formId のみ)
  • fplant:confirmationShowdetail.confirmationEl は含まれません (formId のみ)