3

Scala 的 Play Framework 文档显示了一个将表单隐式映射到案例类的示例:

case class User(name: String, age: Int)

val userForm = Form(
  mapping(
    "name" -> text,
    "age" -> number
  )(User.apply)(User.unapply)
)

我们注意到在这个独特的样本中只使用了原始值。

如果我们做这样的改变怎么样:

case class Car(brandName: String)

case class User(name: String, car: Car)

此外,我们假设表单返回User's name (String) 和 a carId(String)

val userForm = Form(
  mapping(
    "name" -> text,
    "car" -> carRepository.findById(nonEmptyText)  // concept I wish
  )(User.apply)(User.unapply)
)

有没有办法在这个希望的行上实例化一辆汽车,carId例如由表单提供的一些,并确保它carId不是空的String

4

3 回答 3

5

您可以提供Formatter并使用该of[Car]方法。

implicit val carFormat = new Formatter[Car] {
  def bind(key: String, data: Map[String, String]):Either[Seq[FormError], Car] = 
    data.get(key)
      // make sure the method returns an option of Car
      .flatMap(carRepository.findByBrandName _)
      .toRight(Seq(FormError(key, "error.carNotFound", Nil)))

  def unbind(key: String, value: Car) = Map(key -> value.brandName)
}

这个答案提供了另一个FormatterPlay 2 - Scala - Forms Validators and radio buttons

然后你可以像这样使用它:

val userForm = Form(
  mapping(
    "name" -> text,
    "car" -> of[Car]
  )(User.apply)(User.unapply)
)
于 2013-02-25T19:38:24.003 回答
5

对于您问题的第一部分,文档还显示了嵌套值:

case class Car(brandName: String)
case class User(name: String, car: Car)

val userForm = Form(
  mapping(
    "name" -> text,
    "car" -> mapping(
        "brandName" -> text
    )(Car.apply)(Car.unapply)
  )(User.apply, User.unapply)
)
于 2013-02-25T19:30:10.367 回答
2

迟到了,但我刚刚发布了一个实用程序来帮助解决这个问题!使用您的类,您的代码将如下所示:

case class Car(brandName: String)
object Car { implicit val mapping = CaseClassMapping.mapping[Car] }

case class User(name: String, car: Car)
object User { implicit val mapping = CaseClassMapping.mapping[User] }

val userForm = Form(implicitly[Mapping[User]])

您可以在 github 上找到将其包含在项目中的源代码和说明:https ://github.com/Iterable/iterable-play-utils

于 2016-10-11T19:33:58.283 回答