在戏中!框架,使用scala,说我有如下形式:

import play.api.data._
import play.api.data.Forms._
import play.api.data.validation.Constraints._

case class User(someStringField: String, someIntField: Int)

val userForm = Form(
  mapping(
    "someStringField" -> text,
    "someIntField" -> number verifying(x => SomeMethodThatReceivesAnIntAndReturnsABoolean(x))
  )(User.apply)(User.unapply)




其中,SomeMethodThatReceivesAnIntAndReturnsABoolean是一种在int上执行一些逻辑以对其进行验证的方法。

但是,我希望能够在验证someStringField时考虑someIntField的值,有没有办法在游戏框架的形式中实现这一点?我知道我可以做类似的事情:

val userForm = Form(
  mapping(
    "someStringField" -> text,
    "someIntField" -> number
  )(User.apply)(User.unapply)
.verifying(x => SomeFunctionThatReceivesAnUserAndReturnsABoolean(x))


然后我将整个可用的用户实例传递给验证功能。这种方法的问题在于,导致的错误将与整个表单相关联,而不是与someIntField字段相关联。

有没有办法同时使用两个字段来验证一个字段并保持与我要验证的特定字段(而不是整个表单)相关的错误?

最佳答案

根据其他字段的值,向字段添加验证具有相同的要求。我不确定在惯用的PLAY 2.2.1中如何完成此操作,但是我想出了以下解决方案。在这种用法中,我将内置的“映射”降级为一个简单的类型转换器,并在“ validateForm”方法中应用了“高级字段间”验证。映射:

val userForm = Form(
mapping(
  "id" -> optional(longNumber),
  "surename" -> text,
  "forename" -> text,
  "username" -> text,
  "age" -> number
)(User.apply)(User.unapply)
)

private def validateForm(form:Form[User]) = {
  if(form("username").value.get == "tom" || form("age").value.get == "38") {
    form
      .withError("forename", "tom - forename error")
      .withError("surename", "tom - surename error")
  }
  else
    form
}

def update = Action { implicit request =>
  userForm.bindFromRequest.fold({
    formWithErrors => BadRequest(users.edit(validateForm(formWithErrors)))
  }, { user =>
    val theForm = validateForm(userForm.fill(user))
    if(theForm.hasErrors) {
      BadRequest(users.edit(theForm))
    } else {
      Users.update(user)
      Redirect(routes.UsersController.index).flashing("notice" -> s"${user.forename} updated!")
    }
  })
}


即使有效,我仍在紧急寻找更惯用的版本...

编辑:在惯用游戏中使用自定义play.api.data.format.Formatter,更多关于http://workwithplay.com/blog/2013/07/10/advanced-forms-techniques/-这可让您以编程方式向表单添加错误。我的格式化程序如下所示:

val usernameFormatter = new Formatter[String] {

override def bind(key: String, data: Map[String, String]): Either[Seq[FormError], String] = {
  // "data" lets you access all form data values
  val age = data.get("age").get
  val username = data.get("username").get
  if(age == "66") {
    Left(List(FormError("username", "invalid"), FormError("forename", "invalid")))
  } else {
    Right(username)
  }
}

override def unbind(key: String, value: String): Map[String, String] = {
  Map(key -> value)
}
}
}


在表单映射中注册是这样的:

mapping(
[...]
  "username" -> of(usernameFormatter),
[....]

10-07 19:37
查看更多