最初に。余裕のある人は、Play Framework 2.1 を使うことをおすすめしますよ~‥‥
ということで、Java + Play! 2.0 で、複数チェックボックスの値を送信する方法です。
調べた限りでは、どうやら Java + Play! 2.0 の環境では、
multiple checkbox の binding 処理にバグがあるみたい‥‥。
(参考:こことか。)
もちろん、select ボックスの複数選択も同じくできないようですね。
で、この内容、Play! 2.1 では修正されているみたいなんです。(参考:こことか。)
なので、それでもあえて Java + Play! 2.0 で複数チェックボックスを扱わなきゃいけない!
という人以外には、下記の方法はおすすめしないかもしれません。
さて、では本題です。
バグがある。正攻法じゃダメ。じゃあどうするか‥‥ javascript に頼るしかないですねえ。
値を区切り文字を挟んで連結して、hidden 項目に入れて送信しちゃいましょう。
やや面倒ですが、ほかに思いつく楽な方法がありませんから‥‥しょうがないです。
手順はこんな感じ。
1. フォームの submit イベントを拾う。
2. チェックボックスの値を区切り文字を挟みながら連結する。
3. 連結した値は hidden 項目に格納。
4. フォームを送信。
5. 受け取った内容を区切り文字で分割。
ソースを見ていきましょう。
まず html から
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<form name="test_form" method="POST" action="@routes.Test.postPref" id="post_pref"> <div class="form_box"> <h3 class="pref_title"> お好きな都道府県をどうぞ。<input type="button" id="check_all" value="全てチェックする"> <input type="hidden" value="" name="selected_pref" id="selected_pref"> </h3> <div id="pref_list"> <input type="checkbox" id="pref01" value="北海道"><label for="pref01">北海道</label><br> <input type="checkbox" id="pref13" value="東京都"><label for="pref13">東京都</label><br> <input type="checkbox" id="pref17" value="石川県"><label for="pref17">石川県</label><br> <input type="checkbox" id="pref26" value="京都府"><label for="pref26">京都府</label><br> <input type="checkbox" id="pref37" value="香川県"><label for="pref37">香川県</label><br> <input type="checkbox" id="pref47" value="沖縄県"><label for="pref47">沖縄県</label><br> </div> <div><input type="submit" value="決定" id="submit_test_form"> </div> </form> |
チェックボックスは submit 時に値を付ける必要がありませんので、name を宣言していません。
javascirpt はこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* フォームのsubmit時の処理 */ $("#post_pref").submit(function(evt){ if(!confirm("選択した都道府県でいい?")){ evt.preventDefault(); return false; } // チェックボックスの値をhiddenにセットする var prefs = $("#pref_list input:checked") .map(function(){return $(this).val();}) .get().join(","); $("#selected_pref").val(prefs); return true; }); /* 全てチェック */ $("#check_all").click(function(){ if($("#check_all").val()=="全てチェックする"){ // 全てONにする $("#check_all").val("全てチェック解除"); $("#pref_list input:checkbox").attr('checked','checked'); } else { // 全てOFFにする $("#check_all").val("全てチェックする"); $("#pref_list input:checkbox").removeAttr("checked"); } }); /* チェック外された場合 */ $("#pref_list input:checkbox").click(function(){ if(!this.checked) $("#check_all").val("全てチェックする"); }); |
今回はカンマ区切りで連結してみました。
hidden フォームに格納してしまえば、あとは普通のフォームの値と同様に扱えます。
半分以上がおまけの機能=全てチェックするためのボタンのための処理です。
「全てチェック」は、よくチェックボックスで機能を用意してある場合がありますが、
動作の整合性を取るための機能の実装に混乱をきたしがちです。
だったらいっそのことボタンにしちゃったほうが楽でしょ?
次にコントローラー側では、受け取ったフォームの値を区切り文字で分割してあげないといけません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
import java.util.Arrays; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; ~省略~ Form<TestFormData> formData = form(TestFormData.class).bindFromRequest(); if (formData.hasErrors()) { return ok(views.html.test.render("Form.hasErrors:" + formData.errors().toString())); } TestFormData testFormData = formData.bindFromRequest().get(); if (testFormData == null) { return ok(views.html.test.render("data was null")); } String whereString = ""; Pattern delimPattern = Pattern.compile(","); List<String> tmpList = new ArrayList<String>(); for(String tmpStr: Arrays.asList(delimPattern.split(testFormData.selectedPref, 0))){ tmpList.add("pref='" + tmpStr + "'"); } whereString +=" AND ("; whereString += StringUtils.join(tmpList, " OR "); whereString +=")"; Finder<Integer, PREF_TBL> finder = new Finder<Integer, PREF_TBL>(Integer.class, PREF_TBL.class); // 指定した条件で抽出 Query<PREF_TBL> query = finder.where(whereString).orderBy(""); List<PREF_TBL> prefDatas = query.findList(); |
受け取った値は、ここには書いていない TestFormData クラスで受け取ることとします。
また、DB から取得した内容は、これまたここには書いていない PREF_TBL クラスで受け取ることとします。
java.util.regex.Pattern.split で分割した値を java.util.Arrays.asList で配列に保存しています。
あとは org.apache.commons.lang3.StringUtils.join で
区切り文字を入れながら再度連結なんてこともしています。
routes については書いてませんが、一般的な Form の POST 処理で OK ですので、
悩ましいところはないはずです。
いかがでしたでしょうか。
複数チェックボックスの値を扱えない‥‥というところがコマッタさんでしたが、
javascript を使えば難なくクリアできちゃいますよというお話でした。