Play2.0 の Form に自分で定義した Field を加える
Play 2.0 では次のように "name" -> text などのマッピングを定義してコメントのフォームを作ります。
例
case class User(name: String, email: Option[String]) val userForm = Form( mapping( "name" -> text, "email" -> optional(text) )(User.apply, User.unapply) )
このフォームにリクエストを Form#bindFromRequest でバコッと bind するがパターンです。
でも 標準では text, number, date などのようなフィールドしかないです。例えば、 MomoiroCloverZ などのフィールドはないです。全く。困ってしまいますね。
このようなときでも、Formatter[MomoiroCloverZ] を implicit に定義してやれば、MomoiroCloverZ をフィールドとして使えて、bindFromRequest できます。なんでかって?うふふ(めんどい)。
package controllers import play.api._ import play.api.mvc._ import play.api.data._ import play.api.data.Forms._ import play.api.data.format._ case class MomoiroCloverZ(name: String) object Application extends Controller { def momocloGet = Action { Ok(views.html.momoclo(momoCloForm)) } def momocloPost = Action { implicit request => momoCloForm.bindFromRequest.fold( formWithError => Ok(views.html.momoclo(formWithError)) , form => Ok("OK") ) } val momoCloForm = Form( "member" -> of[MomoiroCloverZ] ) implicit def MomoCloFormatter: Formatter[MomoiroCloverZ] = new Formatter[MomoiroCloverZ] { def bind(key: String, data: Map[String,String]): Either[Seq[FormError], MomoiroCloverZ] = { val name = data.getOrElse(key, "") if (name.isEmpty) { Left(Seq(FormError(key, "空だよ!"))) } else if (List("れに", "かなこ", "ももか", "しおり", "あやか").contains(name)) { Right(MomoiroCloverZ(name)) } else { Left(Seq(FormError(key, "だれ?"))) } } def unbind(key: String, value: MomoiroCloverZ): Map[String, String] = Map(key -> value.name) } }
ビューはこんな感じで、ヘルパー便利ですよ。
@(momoClo: Form[MomoiroCloverZ]) @import helper._ <form method="POST" action="./momoclo"> @inputText(momoClo("member")) <input type="submit" name="submit" value="submit" /> </form>