ましめも

技術系メモ

Play Framework 2.1のちょっとした新機能

実はPlay Framework 2.0.xのFormでは同じフィールド名で複数値を受け取ることができない。

<input type="checkbox" name="name" value="value1">
<input type="checkbox" name="name" value="value2">
<input type="checkbox" name="name" value="value3">

例えば、上のようなフォームがあったとして、全てにチェックを入れても一つしか値は格納されない(多分name=value3しか入らない。もしかしたらvalue1かも)。

正確に書くと、request.body.asFormUrlEncodedの時点ではMap[String, Seq[String]]としてちゃんと格納されているのでこれを直接参照すれば"(name -> Seq(value1, value2, value3))"が得られるのだが、form.bindFromRequest()した瞬間に内部的にMap[String, String]に変換され、(name -> value3)となってしまう…。

POSTパラメータ name=value1&name=value2&name=value3
request.body.asFormUrlEncoded Map(name -> Seq(value1, value2, value3))
bindFromRequestした際の内部的なデータ Map(name -> value3)


一応、以下のようにフィールド名に"[番号]"をつけてあげれば複数の値を取得することができる。

<input type="checkbox" name="name[0]" value="value1">
<input type="checkbox" name="name[1]" value="value2">
<input type="checkbox" name="name[2]" value="value3">

コントローラ側の例

  case class AddForm(val name: List[String])

  val addForm = Form(
    mapping(
      "name" -> list(text)
    )(AddForm.apply)(AddForm.unapply)
  )

チェックボックスならこれで解決だが、複数選択可能なセレクトボックス(multiple要素をつけたselect)だとお手上げ。(どう転んでもnameは1つしか指定できないので)

しかし、Play Framework 2.1はこれが改善されており、末尾が"[]"で終わるフィールド名は自動的にname[0], name[1]に変換されるようになった!

POSTパラメータ name=value1&name=value2&name=value3
request.body.asFormUrlEncoded Map(name -> Seq(value1, value2, value3))
bindFromRequestした際の内部的なデータ Map(name[0] -> value1, name[1] -> value2, name[2] ->value3)

↑こんな感じに保存されてる

これで、mappingのlistが使い物になる!やったー (2.0.xでもやってほしい…)