Contact Form 7 / Validation Engine / iCheck を併用時のノウハウ

/ Text by

タイトルそのままの内容ですが WordPress で問い合わせフォームを作る際かなり使われているだろう Contact Form 7 に、リアルタイムなバリデーション チェックを加える jQuery Validation Engine、チェックボックス・ラジオボタンをカスタムデザインに差し替える iCheck プラグインを併用した場合に、それぞれが元々持つ実装時の独特なクセが相まってかなりややこしいことになったので次回迷わないようにメモしておく。


Validation Engine の attach 先

これは Validation Engine 単体の注意点だが、Validation Engine を起動する際の validationEngine('attach') メソッドは form 要素に対して行わなければならない。

$('form').validationEngine('attach');

ドキュメントに “the plugin can only be instanciated on form elements” って書いてあるので当たり前なのだが、どの親要素でも大丈夫だろうという勝手な思い込みで form 要素以外に attach してしまい、うまく動作せず無駄に時間を費やすことになった。忙しい時ほどドキュメントはよく読みましょうの典型例。

バリデーション チェックは Validation Engine に一任する

Contact Form 7 にも Ajax で行うそこそこ機能的なバリデーション チェックの仕組みが備わっていますが、Validation Engine も使うのであれば、バリデーション チェックは Validation Engine に一任し、Contact Form 7 側の機能は一切使わない。使ってもいいけどただ複雑になるだけなのでおすすめできません。

  • フィールドが入力必須か
  • メールアドレス・URL・電話番号のフォーマットが正しいか
  • 数値が指定範囲に収まっているか

Contact Form 7 で可能なこうしたバリデーション チェックは Validation Engine でも行えますし、より柔軟に対応が可能です。

ただし。Contact Form 7 のバリデーション時のエラーメッセージは WordPress の管理画面から変更が可能なのですが、この方法を採るとそれが意味をなさなくなることはデメリットとなるかもしれません。

フィールドへの data 属性追加は JavaScript で行う

Contact Form 7 は独自のショートコードによってフォームの各フィールドを定義する仕様になっています。例えば <input type="text" name="your-name" class="required"> というソースのテキストフィールドを作成する際には

/*

"your-name" という name 属性でかつ
"required" という class 名の付いたテキストフィールドを作りたい場合

*/


[text your-name class:required]

と入力する必要があり、ドキュメントに従えば class や placeholder など出力されるソースの多少のコントロールは可能になっています。一方 Validation Engine ではテキストフィードのバリデーション チェックのコントロールをしようと思うと

/*

入力必須のテキストフィールドで かつ
エラーメッセージをインラインで id="your-name-error" の要素に出力したい場合

*/


<input type="text" name="your-name" class="validate[required]" data-prompt-position="inline" data-prompt-target="your-name-error">

といった具合に、行いたい処理によって class だけでなく data 属性も付加する必要があります。

Contact Form 7 と Validation Engine を組み合わせることを考えると、Contact Form 7 のショートコードから Validation Engine が必要とするソースコードを出力させなければなりませんが、Contact Form 7 にはそもそも data 属性を自由に付加するためのオプションがありません。

なので先ず Contact Form 7 で最低限のソースを出力してから、JavaScript で Validation Engine 用の data 属性を動的に加え、その後 Validation Engine を起動するという方法を使う。

// Contact Form 7 でテキストフィールドを出力
[text your-name]
// JavaScript で上記の出力フィールドに対し class や data 属性を追加する
$('input[name="your-name"]')
    .addClass('validate[required]')
    .attr({
        'data-prompt-position' : 'inline',
        'data-prompt-target'   : 'your-name-error'
    })
;
// バリデーション チェックに必要なオプションが付加されたら Validation Engine を起動
$('form').validation('attach');

バリデーション チェックの内容を Contact Form 7 (WordPress) と JavaScript に分ける形となり一箇所にまとめられないところが非常にややこしいのですがプラグイン自体を改変するという禁じ手を使わないのであればこうする以外にありません。

iCheck 利用時に必要なこと

iCheck を使うことにより、チェックボックスやラジオボタンのデフォルトの UI デザインをオリジナルのものにカスタマイズ可能です。が、iCheck を起動するとそのままでは Validation Engine のリアルタイムなバリデーション チェックが動作しなくなってしまいます。これは iCheck がチェックボックスやラジオボタンの本来のヒット領域を完全に隠してしまい独自のUI・イベントに差し替えてしまうことに起因します。

iCheck によってカスタム化されたチェックボックスやラジオボタンで Validation Engine を利用するには

$('input[type="checkbox"]')
    .on('ifChanged', function() {
        $('form').validationEngine('validate');
    })
;

という具合に iCheck の “ifChanged” イベントに Validation Engine をキックする処理をバインドしてあげれば OK です。

iCheck ラジオボタンと Validation Engine の相性問題

また iCheck のラジオボタンに Validation Engine を適用する際にはさらに注意が必要。同じラジオボタンのグループで現在選択している選択肢から別の選択肢に変更しようとクリックした際に、Validation Engine が一瞬「選択してください」とエラーメッセージを表示させてしまいます。一瞬のことで、別の選択肢のラジオボタンが checked 状態に変わった後はすぐにエラーメッセージは消えてしまうのですが、視覚的にはとても気になる。

どうやら iCheck の内部処理で【現在の選択肢 checked: FALSE】→【クリックした選択肢 checked: TRUE】と状態を変化させる際に一瞬「未選択」の状態が出来るらしく、その一瞬に Validation Engine が反応をしてしまうようです。結論として以下の様にして同じグループのラジオボタンが選択されているかどうか判別式を挿入することで回避可能でした。

$('form').find('input[type="radio"]')
    .on('ifChanged', function() {
        if ($('input[name="' + $(this).attr('name') + '"]:checked').length !== 0) {
            $(this).validationEngine('validate');
        }
    })
;

Validation Engine と iCheck の起動順序

この点についてはこの限りではないかも知れませんが、正常な動作が確認できた順序として

  1. Contact Form 7 にフィールドを定義
  2. Contact Form 7 が出力したフィールドに対し、Validation Engine で行いたいチェックに必要な class や data 属性を JavaScript で動的に付加
  3. $(‘form’).validationEngine(‘attach’) で Validation Engine を起動
  4. チェックボックス・ラジオボタンに対し iCheck を実行し、デザインのカスタム化を行う
  5. iCheck のチェックボックス・ラジオボタンの “ifChanged” イベントに $(‘form’).validationEngine(‘validate’) をバインド

とすることで良さそうです。