a-blog cmsで作るカスタムフィールドの動的フォーム
2.0から簡単なフォームであれば動的フォームが作れるようになりましたが、カスタムフィールドで動的フォームを作ることもできます。カスタムフィールドで作ると、さらに複雑なフォームを作れます。
今回私が作ったものはエントリーのカスタムフィールドの動的フォームです。 エントリーを作成したと同時にフォームの項目を更新することができ、エントリーとフォームの項目が連動しているため、エントリーとフォームの情報のズレがなくなります。
カスタムフィールドの動的フォームはブログやカテゴリーのカスタムフィールドでも作成できます。
途中、でてくるソースコードにはVer.2.0系のclassがあたっていますが、もともとVer.1.7で作成していたので、機能的には1.7でも実装可能です。
実装方法
まずは普段のようフォームを作ります。この静的フォームを完成目標にして動的フォームを作成していきます。
<tr> <th><label for="bus_station">ご希望のバス停</label></th> <td> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station01"><input type="checkbox" name="bus_station[]" value="名古屋駅 13:00発" id="input-bus_station01"{bus_station:checked#名古屋駅 13:00発} /><i class="acms-ico-checkbox"></i> 名古屋駅 13:00発</label> </div> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station02"><input type="checkbox" name="bus_station[]" value="伏見駅 13:10発" id="input-bus_station02"{bus_station:checked#伏見駅 13:10発} /><i class="acms-ico-checkbox"></i> 伏見駅 13:10発</label> </div> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station03"><input type="checkbox" name="bus_station[]" value="栄駅 13:20発" id="input-bus_station03"{bus_station:checked#栄駅 13:20発} /><i class="acms-ico-checkbox"></i> 栄駅 13:20発</label> </div> <input name="field[]" value="bus_station" type="hidden"> </td> </tr>
フォームの項目を入力するカスタムフィールドを作る
静的なフォームを作ったら、今度は編集ページにカスタムフィールドを作ります。ここまでは普段通りです。
<h3 class="acms-admin-title2">ご希望のバス停</h3> <table class="adminTable acms-table-admin-edit" style="margin-bottom:30px"> <tr> <th>フォームに表示する</th> <td> <label for="appearForm" class="acms-form-checkbox"><input type="checkbox" name="appearForm" value="true" id="appearForm"{appearForm:checked#true} /><i class="acms-ico-checkbox"></i>表示する</label> <input type="hidden" name="field[]" value="appearForm" /> </td> </tr> <tr> <th>駅1</th> <td> <div class="acms-form-block"> <input type="text" name="bus_station01" value="{bus_station01}">駅 </div> <input type="hidden" name="field[]" value="bus_station01"> <input type="text" name="bus_hour01" value="{bus_hour01}"> <input type="hidden" name="field[]" value="bus_hour01">: <input type="text" name="bus_minute01" value="{bus_minute01}"> <input type="hidden" name="field[]" value="bus_minute01"> </td> </tr> <tr> <th>駅2</th> <td> <div class="acms-form-block"> <input type="text" name="bus_station02" value="{bus_station02}">駅 </div> <input type="hidden" name="field[]" value="bus_station02"> <input type="text" name="bus_hour02" value="{bus_hour02}"> <input type="hidden" name="field[]" value="bus_hour02">: <input type="text" name="bus_minute02" value="{bus_minute02}"> <input type="hidden" name="field[]" value="bus_minute02"> </td> </tr> <tr> <th>駅3</th> <td> <div class="acms-form-block"> <input type="text" name="bus_station03" value="{bus_station03}">駅 </div> <input type="hidden" name="field[]" value="bus_station03"> <input type="text" name="bus_hour03" value="{bus_hour03}"> <input type="hidden" name="field[]" value="bus_hour03">: <input type="text" name="bus_minute03" value="{bus_minute03}"> <input type="hidden" name="field[]" value="bus_minute03"> </td> </tr> </table>
フォームを動的にする
動的にしたいフォームの項目をビルトインモジュールで囲みます。使用するビルトインモジュールは、表示させたい情報によって選んでください。
ビルトインモジュールの記述で囲んだら、必要に応じて、モジュールにIDをつけてどのエントリーを表示するか設定します(ちなみに、私の場合は「フォームを表示する」チェックボックスのカスタムフィールドを作り、この値が入っていたエントリーだけ表示する設定にしています)。
value、フォームの変数、ラベルをカスタムフィールドの変数に変更します。下記の例では、フォームの変数でバックスラッシュを使っていますが、後のパブリッシュの項目で説明します。
テンプレートの記述例:
<tr> <th><label for="bus_station">ご希望のバス停</label></th> <td> <!-- BEGIN_MODULE Entry_Summary id="bus_station" --> <!-- BEGIN unit:loop --> <!-- BEGIN entry:loop --> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station01"><input type="checkbox" name="bus_station[]" value="{bus_station01}駅 {bus_hour01}:{bus_minute01}発" id="input-bus_station01"\{bus_station:checked#{bus_station01}駅 {bus_hour01}:{bus_minute01}発\} /><i class="acms-ico-checkbox"></i> {bus_station01}駅 {bus_hour01}:{bus_minute01}発</label> </div> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station02"><input type="checkbox" name="bus_station[]" value="{bus_station02}駅 {bus_hour02}:{bus_minute02}発" id="input-bus_station02"\{bus_station:checked#{bus_station02}駅 {bus_hour02}:{bus_minute02}発\} /><i class="acms-ico-checkbox"></i> {bus_station02}駅 {bus_hour02}:{bus_minute02}発</label> </div> <div class="acms-form-block"> <label class="acms-form-checkbox" for="input-bus_station03"><input type="checkbox" name="bus_station[]" value="{bus_station03}駅 {bus_hour03}:{bus_minute03}発" id="input-bus_station03"\{bus_station:checked#{bus_station03}駅 {bus_hour03}:{bus_minute03}発\} /><i class="acms-ico-checkbox"></i> {bus_station03}駅 {bus_hour03}:{bus_minute03}発</label> </div> <!-- END entry:loop --> <!-- END unit:loop --> <!-- END_MODULE Entry_Summary --> <input name="field[]" value="bus_station" type="hidden"> </td> </tr>
パブリッシュ
変数が入れ子になっている(例:{bus_station:checked#{bus_station02}駅 {bus_hour02}:{bus_minute02}発}
)ので、一度パブリッシュする必要があります。
そのときはフォームの変数のほうの{
、}
の前にバックスラッシュを入れてパブリッシュします(例:\{bus_station:checked#{bus_station02}駅 {bus_hour02}:{bus_minute02\}発
)。バックスラッシュを前に入れた{
、}
は、パブリッシュしたときに変換されません。入れ子になっているカスタムフィールドの変数はパブリッシュしたいので、バックスラッシュをつけなくて大丈夫です。
カスタムフィールドの部分だけパブリッシュしたいため、カスタムフィールのフォームの項目だけ新しくインクルードファイルを作ります。パブリッシュの管理画面内で指定したテーマ内に置いてください。 例)/themes/site2001/contact/form_include/bus_station_dynamic.html
管理画面→パブリッシュの順にページに移動します。
生成元URI | さきほど作ったインクルードファイルを、httpからURLを記述するか、もしくはacmsパスで記述します。 |
---|---|
出力先パス | ファイルがあるテーマフォルダを選び、パブリッシュ後のファイル名を記入します。 |
記入したら、「保存」をします。保存をしてから、保存ボタンの左にある「パブリッシュを実行する」ボタンをクリックします。
指定したテーマフォルダの直下にパブリッシュ後のファイルが正しく作成されているか確認します。
作成したパブリッシュ後のファイルをフォームのテンプレートにインクルードで読み込みます。 例)<!-- #include file="/bus_station_static.html" -->
confirm.htmlの書き方
<tr> <th>ご希望のバス停</th> <td> <!-- BEGIN bus_station:loop --> {bus_station} <!-- END bus_station:loop --> </td> </tr>
普段の複数選択するときのチェックボックスの書き方と同じです。メールのtxtファイルも同じ書き方で大丈夫です。
entry:loopを使ったフォームの実装
エントリーループをつかって実装することもできます。
entry:loopを使った動的フォームの使うことで、フォームの項目とエントリーを連動できます。エントリーはないのに、フォームの項目がそのまんま、という状態を防げます。
複数のエントリーで登録したカスタムフィールドを表示するには、エントリーごとに値を分ける必要があります。同じ値があると、正しく動的フォームが動作しなくなるためです。ここでは、エントリーごとに値が違う、eid
を使います。
このとき、カスタムフィールドグループのループの中ではeid
の変数が使えないので、あらかじめ、エントリーのカスタムフィールドでhidden
で値を渡します。
カスタムフィールドグループのループでhidden
で値を渡したときの例:
<table class="js-fieldgroup-sortable adminTable acms-table-admin-edit"> <!-- BEGIN group_bus:loop --> <tr class="sortable-item"> <td class="item-handle"><img width="17" height="17" class="arrowHandle" src="/images/admin_arrow_vertical.gif" /></td> <td> <table class="nestTable"> <tr> <th>バス出発時間{i}</th> <td> <div class="acms-form-group"> <input type="text" name="bus_station[{i}]" value="{bus_station}">駅 </div> <input type="text" name="bus_hour[{i}]" value="{bus_hour}">:<input type="text" name="bus_minute[{i}]" value="{bus_minute}">発 <input type="hidden" name="eid_same[{i}]" value="%{EID}" /> </td> </tr> </table> </td> <td><input type="button" class="item-delete acms-btn-admin acms-btn-admin-danger" value="削除" /></td> </tr> <!-- END group_bus:loop --> <tr class="sortable-item item-template"> <td class="item-handle"><img width="17" height="17" class="arrowHandle" src="/images/admin_arrow_vertical.gif" /></td> <td> <table class="nestTable"> <tr> <th>バス出発時間{i}</th> <td> <div class="acms-form-group"> <input type="text" name="bus_station[]" value="">駅 </div> <input type="text" name="bus_hour[]" value="">:<input type="text" name="bus_minute[]" value="">発 <input type="hidden" name="eid_same[]" value="%{EID}" /> </td> </tr> </table> </td> <td><input type="button" class="item-delete acms-btn-admin acms-btn-admin-danger" value="削除" /></td> </tr> <tfoot> <tr> <td colspan="3"><input type="button" class="item-insert btnAddition acms-btn-admin acms-btn-admin-primary" value="+ 項目を追加する" /></td> </tr> </tfoot> </table> <input type="hidden" name="@group_bus[]" value="bus_station" /> <input type="hidden" name="field[]" value="bus_station" /> <input type="hidden" name="@group_bus[]" value="bus_hour" /> <input type="hidden" name="field[]" value="bus_hour" /> <input type="hidden" name="@group_bus[]" value="bus_minute" /> <input type="hidden" name="field[]" value="bus_minute" /> <input type="hidden" name="@group_bus[]" value="eid_same" /> <input type="hidden" name="field[]" value="eid_same" /> <input type="hidden" name="field[]" value="@group_bus" />
例)パブリッシュ前のフォームのカスタムフィールドグループのソース
<tr> <th><label for="bus_station">ご希望のバス停</label></th> <td> <!-- BEGIN_MODULE Entry_Summary id="bus_station" --> <!-- BEGIN unit:loop --> <!-- BEGIN entry:loop --> <div class="acms-form-group"> <label class="acms-form-checkbox"><input type="checkbox" name="bus_title{eid}" value="{title}"\{bus_title{eid}:checked#{title}\} class="js-open_campus_value" /><i class="acms-ico-checkbox"></i> {title}</label> <input type="hidden" name="field[]" value="bus_title{eid}" /> <select name="bus_time{eid}" class="js-open_campus_value"> <option value="">バス予約時間を選択してください</option> <optgroup label="{title}"> <!-- BEGIN group_bus:loop --> <option value="{bus_station}駅({bus_hour}:{bus_minute}発)"\{bus_time{eid_same}:selected#{bus_station}駅({bus_hour}:{bus_minute}発)}>{bus_station}駅({bus_hour}:{bus_minute}発)</option> <!-- END group_bus:loop --> </optgroup> <option value="送迎バスは利用しない"\{bus_time{eid}:selected#送迎バスは利用しない}>送迎バスは利用しない</option> </select> <input type="hidden" name="field[]" value="bus_time{eid}" /> </div> <!-- END entry:loop --> <!-- END unit:loop --> <!-- END_MODULE Entry_Summary --> <input name="field[]" value="bus_station" type="hidden"> </td> </tr>
エントリーのループを使ってカスタムフィールドを作成している場合、確認画面と、メールのtxtファイルもパブリッシュしてください。カスタムフィールドの変数と一緒にフォームの変数をパブリッシュしてしまわないために、フォームの変数にはバックスラッシュをつけるのを忘れないでください。
例)confirm.html
<!-- BEGIN_MODULE Entry_Summary id="bus_station" --> <tr> <th>バス予約時間</th> <td><!-- BEGIN unit:loop --><!-- BEGIN entry:loop -->\{bus_title{eid}\}: \{bus_time{eid}\} <!-- END entry:loop --><!-- END unit:loop --> </td> </tr> <!-- END_MODULE Entry_Summary -->
例)メールのtxtファイル
ご希望のバス停: <!-- BEGIN_MODULE Entry_Summary id="bus_station" --><!-- BEGIN unit:loop --><!-- BEGIN entry:loop -->\{bus_title{eid}\}: \{bus_time{eid}\} <!-- END entry:loop --><!-- END unit:loop --><!-- END_MODULE Entry_Summary -->
フォーム、確認画面のテンプレートをパブリッシュしたら、フォームのテンプレートにそれぞれのパブリッシュしたファイルを読みこみます。
メールのtxtファイルはインクルードで読み込むことができないので、丸ごとパブリッシュします。
更新方法の問題点
仕組みは作れましたが、このままだと、運営者が更新しにくい状態になっています。カスタムフィールドの更新する、内容を変更するたびに、管理画面のパブリッシュのページに移動しなくてはいけないからです。 そういうときは、少しカスタマイズして、更新しやすい場所にパブリッシュボタンを作ります。 ボタンは、表のテンプレートにも表示できるので、運営者が管理画面内で迷子になるのを防止できます。
<!-- BEGIN_MODULE Admin_Publish_Index --> <!-- BEGIN allow --><!-- BEGIN_MODULE Touch_SessionWithAdministration --> <div class="titleWrapper"> <h2>パブリッシュ実行</h2> </div> <div class="contents"> <p>お問い合わせの項目を変更したら、以下のパブリッシュボタンを実行してください。</p> <form action="" method="post"> <input type="submit" name="ACMS_POST_Publish_Apply" value="パブリッシュを実行する" onclick="出力先" class="acms-btn-admin acms-btn-admin-info" /> </form> </div><!-- END_MODULE Touch_SessionWithAdministration --> <!-- END allow --> <!-- END_MODULE Admin_Publish_Index -->
ただ、エラーが出ているかわからないので、制作途中は管理画面の「パブリッシュを実行する」ボタンからパブリッシュを使うことをおすすめします。
作成するポイント
複雑なことをしているので、実装中によくわからなくなりやすいです。 もしなんらかのミスで上手く表示していないときは、
- ファイルのパスが正しいか確認する
- 初めに作った静的フォームのテンプレートと見比べてパブリッシュしたHTMLファイルが正しく出力されているか確認する
上記2点をお確かめください。大体、私は上記の2つを確認しながら、凡ミスを発見していました。