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>



あやかはいるので



OKです。




マツコはまだ加入してません。


エラーです。