Validation scala中的条件映射
使用play 2.x,我有以下表单映射:Validation scala中的条件映射,validation,scala,playframework-2.0,Validation,Scala,Playframework 2.0,使用play 2.x,我有以下表单映射: val relocationDtoForm: Form[RelocationDto] = Form( mapping( "_type" -> text, "sourceToken" -> text, "exchange" -> optional(jodaDate("dd/MM/yyyy")), "completion" -> optional(jodaDate("dd/MM/yyyy")),
val relocationDtoForm: Form[RelocationDto] = Form(
mapping(
"_type" -> text,
"sourceToken" -> text,
"exchange" -> optional(jodaDate("dd/MM/yyyy")),
"completion" -> optional(jodaDate("dd/MM/yyyy")),
"expectedMoveIn" -> optional(jodaDate("dd/MM/yyyy"))
)(RelocationDto.apply)(RelocationDto.unapply)
)
我想添加验证,以便如果_type==“sale”,则exchange是必填字段,但如果_type==“let”,则ExpectedMovien是必填字段。我似乎找不到一种使用标准播放验证程序的方法,有什么方法可以做到这一点吗
干杯
Nic您可以使用
映射的验证方法。这将允许您在表单成功绑定到类后创建约束,您可以在该类中访问其他字段。它接受错误消息和布尔函数,当false
时,该函数将向表单中添加错误
val relocationDtoForm: Form[RelocationDto] = Form(
mapping(
"_type" -> text,
"sourceToken" -> text,
"exchange" -> optional(jodaDate("dd/MM/yyyy")),
"completion" -> optional(jodaDate("dd/MM/yyyy")),
"expectedMoveIn" -> optional(jodaDate("dd/MM/yyyy"))
)(RelocationDto.apply)(RelocationDto.unapply)
.verifying(
"Exchange is required for sales.",
relocationRto => if(relocationRto._type == "sale") relocationRto.isDefined else true
).verifying(
"Expected move in is required for let?",
relocationRto => if(relocationRto._type == "let") expectedMoveIn.isDefined else true
)
)
我最终的解决方案是:
def save(id: String) = Action { implicit request =>
//Runs some extra validation based on the _type value
def typeSpecificValidate(params: Map[String,Seq[String]]): Seq[FormError] = params("_type") match {
case Seq("sale") => {
Forms.tuple(
"exchange" -> jodaDate("dd/MM/yyyy"),
"completion" -> jodaDate("dd/MM/yyyy")
).bind(params.mapValues(seq => seq.head)) match {
case Left(errors) => errors //Bind returns a Left(List(FormErrors)) or a Right(boundTuple)
case _ => Nil
}
}
case Seq("let") => {
Forms.tuple(
"expectedMoveIn" -> jodaDate("dd/MM/yyyy")
).bind(params.mapValues(seq => seq.head)) match {
case Left(errors) => errors //Bind returns a Left(List(FormErrors)) or a Right(boundTuple)
case _ => Nil
}
}
}
val extraErrors = typeSpecificValidate(request.body.asFormUrlEncoded.get)
Logger.debug("Custom validator found: " + extraErrors)
val ff = relocationDtoForm.bindFromRequest
ff.copy(errors = ff.errors ++ extraErrors).fold(
formWithErrors => {
formWithErrors.errors.foreach(e => Logger.debug(e.toString))
BadRequest(views.html.relocations.detail(id, formWithErrors))
},
relocationDto => {
Logger.debug(relocationDto.toString)
Ok(views.html.relocations.detail(id, relocationDtoForm.fill(relocationDto)))
}
)
}
我曾为英国税务海关总署(英国)工作,看起来HMRC已经公开了一个非常有用且易于使用的库,专门用于条件播放映射:啊,是的,我尝试过,但问题是,由此产生的错误不会局限于字段,只会在表单级别。我需要在随后向用户演示时将该字段标记为无效。有可能吗?对于表单映射,情况似乎并非如此。表单字段在绑定到某个对象之前彼此不了解任何信息。当验证依赖于多个类似的字段时,错误真的应该绑定到一个字段吗?如果您真的想这样做,那么看起来您必须在表单之外验证您的对象(一旦绑定),并使用withError
自己添加错误。我需要这样做的原因是我的表单和dto是多用途的,并且映射到两个案例类中的一个。在我尝试这样做之前,我需要验证它是否映射为ok(基于_类型)。因此,我认为有必要这样做,正如您所建议的,尽管在控制器中使用手动验证看起来是目前的做法。谢谢NFV@nfvindaloo您可以使用LimbGroup的验证机制并将错误绑定到表单元素。我已经在这里的另一个问题中回答了这个问题: