Viewではjavascriptコードとformのhtmlコードを出力する
form helperとjs helperの役割を同等と考える
Ajaxメールフォームにおいて最も重要なのはViewになるのかもしれない。そのviewでやることは以下の2点に集約できる。
・jsコードの生成
・form htmlの生成
通常viewで行うのはhtmlの生成と出力、あるいは出力のみであるが、Ajaxメールフォームにおいては、本ブログの場合jsコードの出力が追加される。form helperとjs helperはいずれもCakephpのヘルパー機能であり、この二つのコード出力機能を意識しておくと良いかなと考えている。
作成するviewファイルは、
app\View\Pages\contact.ctp
になる。
js部分
以下javascript部分のコードとする。冒頭のコメント1の箇所の$optionListはjsコードではなくcontroller側で定義しても良かったのだが、view側に書いておいたほうが理解しやすいと判断しview側に書くことにした。$optionListはフォームのセレクトボックスのオプションリストを配列にしてあり、form部分のコードで利用することになっている。
// コメント1.select boxのリスト $optionList = array( array( 'id' => 'opt1', 'value' => '1', 'name' => '利用方法', ), array( 'id' => 'opt2', 'value' => '2', 'name' => '要望', ), array( 'id' => 'opt3', 'value' => '3', 'name' => 'その他', ), ); // コメント2.jsヘルパーを利用せずダイレクトにjavascriptやjqueryコードを書くこともできる $reset = <<< EOF $('form')[0].reset(); EOF; $button_disable = <<< EOF $('div.submit input').attr('disabled', 'disabled'); EOF; $button_enable = <<< EOF $('div.submit input').removeAttr('disabled'); EOF; $error_set = <<< EOF $('#error-set').html(XMLHttpRequest.responseText); EOF; // コメント3.jsヘルパーを利用してjavascriptコードを生成している $before = $this->Js->get('#sending')->effect('fadeIn', array('buffer' => false)); $before .= $this->Js->get('#error-set')->effect('fadeOut', array('buffer' => false)); $before .= $this->Js->get('#thanks')->effect('fadeOut', array('buffer' => false)); $before .= $button_disable; $success = $this->Js->get('#sending')->effect('fadeOut', array('buffer' => false)); $success .= $this->Js->get('#error-set')->effect('fadeOut', array('buffer' => false)); $success .= $button_enable; $success .= $reset; $success .= $this->Js->get('#thanks')->effect('fadeIn', array('buffer' => false)); $error = $this->Js->get('#sending')->effect('fadeOut', array('buffer' => false)); $error .= $button_enable; $error .= $error_set; $error .= $this->Js->get('#error-set')->effect('fadeIn', array('buffer' => false));
select boxのリスト配列の下(コメント2以降)が、javascriptのコードを生成する処理になる。
正確には、
コメント2の箇所はjsヘルパーを利用して生成できないjavascriptコードを手動で書いている部分
ということになる。
コメント3の箇所では、Cakephpのjsヘルパーを利用して生成できるjavascriptコードと、生成できずに開発者がコーディングした純粋なjavascript(jquery)コードを変数にまとめている処理が書いてある。
Cakephpのjs helperは便利で強力なjavascript生成機能を持っているが万能ではなく、上のコメント2で書いてあるように開発者自身がjavascriptコードを書かなければならないコードがあるということである。
逆にいうと、上のコードのようにphpのヒアドキュメントを活用して純粋なjavascriptをすべて書いてしまっても良い。
上記のコードでは、最終的に
$before
$success
$error
という変数を準備する作業を行っている。この変数内にはjavascriptコードが格納されている。そのコードを生成するためにcakephpのjs helperを利用したということになる。html helperを利用してhtmlコードを生成することと同じ考え方をしている。
上で設定した変数をAjaxリクエストのコールバック関数として設定することで、リクエストとその結果に応じて様々な挙動を設定できるようになる。具体的には、
リクエストの前の段階で$before内のjsでフォームボタンを無効化
リクエストの結果HTTPエラーが返されたのであればXMLHttpRequestオブジェクトからエラーメッセージを取得
といった感じでAjaxリクエスト周りの設定をすることができる。
form部分
次にform部分(htmlコード)である。上で載せたjs部分のコードの下に以下のコードを足したものがメールフォームのviewファイルになる。foundation5のgrid layoutでフォームを組んであるのでその点も参考にしてほしい。
echo "<article>"; echo "<header>"; echo "<h1>お問い合わせフォーム</h1>"; echo "</header>"; echo "<section>"; echo "<div class='large-12 columns'>"; echo "<div class='row'>"; echo $this->Form->create('Contact', array('type'=>'post')); echo "<fieldset>"; echo "<legend>お問い合わせフォーム</legend>"; echo "<div id='error-set' style='display:none;'></div>"; echo "<div class='row'>"; echo "<div class='large-12 columns'>"; echo $this->Form->label('件名'); echo $this->Form->text('title', array('placeholder' => 'お問い合わせの件名を記入してください')); echo $this->Form->error('Contact.title'); echo "</div>"; echo "</div>"; echo "<div class='row'>"; echo "<div class='large-12 columns'>"; echo $this->Form->label('メールアドレス'); echo $this->Form->text('email', array('placeholder' => 'メールアドレスを記入してください')); echo $this->Form->error('Contact.email'); echo "</div>"; echo "</div>"; echo "<div class='row'>"; echo "<div class='large-12 columns'>"; echo $this->Form->input('option', array( 'type' => 'select', 'id' => 'select-category', 'class' => 'large', 'label' => '種類を選択', 'options' => $optionList, 'default' => '1', //'selected' => $selected_id )); echo $this->Form->error('Contact.option'); echo "</div>"; echo "</div>"; echo "<div class='row'>"; echo "<div class='large-12 columns'>"; echo $this->Form->label('お問い合わせの内容'); echo $this->Form->textarea('body', array('placeholder' => 'こちらにお問い合わせの内容を記入してください', 'rows' => '6')); echo $this->Form->error('Contact.body'); echo "</div>"; echo "</div>"; echo "<div class='row'>"; echo "<div class='small-3 large-2 columns'>"; echo $this->Js->submit('送信する', array( 'url' => '/contact', 'before' => $before, 'success' => $success, 'error' => $error, 'update' => '#result-ajaxupdate' )); echo "</div>"; echo "<div class='small-9 large-10 columns'>"; echo "<div id='sending' style='display:none;'>通信中です</div>"; echo "<div id='thanks' style='display:none;'>以下の内容でお問い合わせを受け付けました</div>"; echo "</div>"; echo "</div>"; echo "</fieldset>"; echo $this->Form->end(); echo "<div id='result-ajaxupdate'>"; echo "</div>"; echo "</div>"; echo "</div>"; echo "</section>"; echo "</article>";
この中でAjaxに関連する部分を補足してみようと思う。
13行目の
echo "<div id='error-set' style='display:none;'></div>";
この部分は、$errorのjsで#error-setをidとしてjs側からセレクトされる。またエラー時には、このタグ内にエラーメッセージが格納されるようになっている。つまりformにエラーが発生したときにはこの部分を利用してエラーを表示する。そのエラーはModelのvalidationエラーである。また、htmlに直接であるが非表示のcssを設定して、初回表示時は画面に現れないようにしている。
65, 66行目の
echo "<div id='sending' style='display:none;'>通信中です</div>"; echo "<div id='thanks' style='display:none;'>以下の内容でお問い合わせを受け付けました</div>";
この部分も
display:none;
を設定してあり、個別にidを割り当てている。idによってjs側から操作されるhtmlで、フォームのボタンが押されたときに通信中であることをユーザーに知らせるメッセージや、問題なく問い合わせを受け付けた結果としての送信完了メッセージを予め用意してある。
js部分のコード内で
sending
thanks
といったidでセレクトしている。
56行目からの以下の部分がフォームの送信ボタンを生成する部分になっている。
echo $this->Js->submit('送信する', array( 'url' => '/contact', 'before' => $before, 'success' => $success, 'error' => $error, 'update' => '#result-ajaxupdate' ));
みると分かるかもしれないが、js helperのコードである。つまり、javascriptコードを生成する部分になっている。このコードの引数にjs部分で定義した3つの変数をコールバック関数として設定している。
リクエスト先のURLは、
/contact
である。Controller編でAjaxリクエストの判定処理を行ったことを思い出してほしい。このjsで生成されたフォームボタンを押すとAjaxリクエストが送信され、そのリクエストを受け付けるControllerにはAjaxリクエスト判定処理が設定済みである。
update引数にも注目してほしい。これはリクエストの結果として受けた内容を表示(書き換え)する場所を指定するためのオプションである。
#result-ajaxupdate
と指定してあるとおり、73行目からの
echo "<div id='result-ajaxupdate'>"; echo "</div>";
の部分にリクエストで得た内容をHTMLとして格納する場所になる。今回のAjaxメールフォームの場合は、Controller編で呼び出し設定がしてあるelementが返すhtmlがこの部分に格納されるようになっている。なお、update引数で設定した箇所が更新されるのは、Ajaxリクエストが正常に完了した場合で、エラー時はupdateされないようになっている。
js helperで生成したjavascriptコードはどこに出力されるのか?
上の
$this->Js->submit();
でAjaxに対応したフォームのsubmitボタンが生成される。が、Ajax系のjsコードはどこに出力されるのだろうか?準備編の中でlayoutファイルの下の方に以下のコードが書かれているので確認してほしい。
echo $this->Js->writeBuffer(array('inline' => 'true'));
上のコードが書かれている部分にjs helperで生成したコードが出力されるようになっている。javascriptコードをためておいて最後にはき出すイメージである。
view編の次はelement編になる。