デザイナーの伊東です。
今日はデザインのことではなく、フロントエンドよりのことについて書こうと思います。
現在進行中の案件で、お問い合わせフォームを実装することになりました。
Wordpressに組み込む予定のサイトで、フォームには使い慣れているMW WP Formを使用したいと考えていました。が、Wordpressのフォーム系プラグインにはなぜか、リアルタイムバリデーションが実装されているものがないんです。
リアルタイムバリデーションとは、フォームの送信ボタンを押して初めてエラーが表示されるのではなく、入力し終わるとすぐにメッセージが出るタイプのバリデーションのことです。
静的ページの場合は、リアルタイムバリデーションを有効にできるメールフォームプロというツールを使うのですが、Wordpressに組み込むのは少し手間がかかります。。
そこで!以前から気になっていた”knockout.js“というフレームワークを使って、MW WP Formのフォームにリアルタイムバリデーション機能を追加する方法をご説明します。
knockout.jsとは
“MVVM”という考え方
まずは予備知識として、knockout.jsがどういうものかというところをご説明していきます。
knockout.jsは、「MVVM(Model-View-ViewModel)パターンをサポートするためのJavaScriptフレームワーク」という形で度々説明されます。
フレームワークとして使用するので、jQueryのようなライブラリとの併用も可能です。
ここでMVVMという難しい言葉が出てきました。MVVMの説明としては、以下の記事の一文がわかりやすいです。
- システム全体をクライアントサイドとサーバサイドに分ける。
- MVVMはクライアントサイドのコードに適用されるパターンなのでサーバサイドについては関知しない。
- クライアントサイドとサーバサイドの連携には通常、AJAX(SOAP、RESTなど)が使われる。
- クライアントサイドのコードを、HTMLの都合が関係ある部分=プレゼンテーション(Presentation)とHTMLの都合が関係ない部分=ドメイン(Domain)とに分ける
- プレゼンテーションを、UIのテンプレートを定義するHTML/CSS=ビュー(View)と、UIの状態の保持、およびUIから呼び出されるメソッドを定義したJavaScript=ビューモデル(ViewModel)とに分ける
引用元:MVVMフレームワーク「Knockout.js」が超絶便利!!その概要と使いどころなどについて
言葉を噛み砕いて簡単に説明すると、デザイナーが作る”UI”やそれを構築する”マークアップ”の部分と、エンジニアが触る”システム”の部分の切り分けを明確にするのがMVVMの考えということです。
knockout.jsは、そのMVVMを利用してWebアプリケーションを構築するためのフレームワークということです。
knockout.js導入に向いているケース
knockout.jsは、ページ遷移なしで頻繁にUIが変化する(DOMの書き換えが行われる)Webアプリケーションの構築に向いています。
そういったWebアプリケーションのことを”シングルページアプリケーション(SPA)“と呼びます。
反対に、ユーザーの操作に合わせてページが遷移する通常のWebサイトの場合は、jQueryなどで部分的にDOMを操作する方が早いかもしれません。
今回は、入力フォームの値に合わせて即時に表示を変えるリアルタイムバリデーションに使用するので、knockout.jsはぴったりです。
jQueryとknockout.jsのアプローチの違い
jQueryは、javascriptのコードでDOM要素を扱う点において非常に優れたライブラリです。DOM要素につけられた”id”や”class”を参照して操作します。
それに対してknockout.jsは、先ほどご説明した「UIとシステムの切り分け」という観点から、直接DOMを操作するということをしません。ではどうやってUIとシステムを紐付けするのでしょうか?そこで登場するのが”データバインディング“という手法です。
具体的に説明すると、htmlのタグに”data-bind“という属性を記述してシステム側とやりとりを行います。
バリデーションのサンプルを動かす
まずは静的ページで実装する
それでは、上記の説明を踏まえて実際にknockout.jsを使ってバリデーションを実装しましょう!
See the Pen GMgRyE by ito nao (@chokuro) on CodePen.
まずはhtmlに”jquery.js”、”knockout.js”、”knockout.validat.js”の3種類を読み込みます。
最後のknockout.validat.jsにはバリデーション機能を実装する上で使える関数などが記述されています。
上記のファイルを読み込んだら、html側に入力欄とエラーメッセージが表示される空のdivを用意しておきましょう。
この時使用するのが”data-bind”属性です。今回はinputタグの親要素に”validationElement”、inputタグに”textinput”、メッセージが入る空のdivに”validationMessage”というプロパティを指定しました。
ちなみに各プロパティは任意の文字列ではなく、”knockout.js”、または”knockout.validat.js”で定義されたプロパティです。
それぞれシステム側とやりとりするための目印だと思っていただいたらいいかと思います。
次にjsの記述を見てみましょう。
以下の部分でバリデーションのルールとそのルールに対する結果を定義します。
1 2 3 4 5 6 7 8 9 10 11 |
function myViewModel() { var self = this; self.email = ko.observable().extend({ required: { message: '必須項目です!' }, email: { message: 'メールアドレスの記述が間違っています!' } }); } |
“required”と”email”という部分は”knockout.validat.js”で定義された文字列です。それぞれ入力の有無と、メールアドレスとして正しい文字列かどうかを判断し、falseの場合の文字を設定します。
次に以下の部分でバリデーションの初期設定を行います。
1 2 3 4 |
ko.validation.init({ insertMessages: false, errorElementClass: 'has-error' }); |
“insertMessages”を”true”にすると、”validationMessage”に表示されるメッセージとは別に、inputタグの直後にメッセージが表示されます。任意の場所に表示させたいのであれば、ここは”false”で構いません。
“errorElementClass”には、エラー時に付与するclass名を指定できます。
このclassは、”validationElement”を定義したDOM要素に対して付与されます。
最後の2文で、今まで定義・初期設定をしてきたバリデーションを作動させます。
1 2 |
var viewModel = ko.validatedObservable(new myViewModel()); ko.applyBindings(viewModel); |
作動させてしまえば、”textinput”に入力された値に対してバリデーションが発動し、結果に合わせてメッセージを表示するという動きが完成します。
MW WP Formでバリデーションを動かしてみる
静的ページで動作確認ができたところで、いよいよ、本題であるwordpressのフォームプラグインと組み合わせてみます。
ここまでくればゴールは後少しです!
wordpressでも同様に、”jquery.js”、”knockout.js”、”knockout.validat.js”の3種類のファイルは読み込ませてください。
以下のjsの記述はそのまま使えそうですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$(function() { function myViewModel() { var self = this; self.email = ko.observable().extend({ required: { message: '必須項目です!' }, email: { message: 'メールアドレスの記述が間違っています!' } }); } ko.validation.init({ insertMessages: false, decorateElement: true, errorElementClass: 'has-error' }); var viewModel = ko.validatedObservable(new myViewModel()); ko.applyBindings(viewModel); }) |
後は、MW WP Formのフォーム作成画面で必要なところに”data-bind”属性をつけてあげましょう。
と言いたいところですが、
実はMW WP Formでは、classやtypeなどの通常htmlで使用されている属性以外は設定できないことがわかりました!
inputタグを生成する画面に任意の属性を追加する項目はなく。。
仕方なく手動で入力してみましたが反映されませんでした。。
そこで、inputタグに特定のclassをつけ、そのclassに対してjsで”data-bind”属性を付与するというやり方で対処しました。
下記のコードをバリデーションの定義より前に挿入します。
1 |
$('.target_email').attr("data-bind","value: email"); |
後はMW WP Formのinputタグ挿入時に、”target_email”というclassをつけてあげると問題なくバリデーションが機能しました!
注意点
今回ご紹介した方法は、htmlの役割とシステムの役割が混同してしまっているので、MVVMの考え方にはそぐわない部分があります。
そのことを理解した上で、Wordpressでリアルタイムバリデーションを実装する場合は、参考にしていただければ幸いです。