播放scala中的条件映射

时间:2014-03-18 22:30:56

标签: 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")),
    "expectedMoveIn" -> optional(jodaDate("dd/MM/yyyy"))
  )(RelocationDto.apply)(RelocationDto.unapply)
)

我想添加验证,以便if _type ==“sale”,则exchange是必填字段,但如果_type ==“let”则expectMoveIn是必填字段。我似乎无法通过标准游戏验证器找到一种方法,有没有办法做到这一点?

干杯 NIC

3 个答案:

答案 0 :(得分:1)

我曾经为女王陛下的收入和海关(英国)工作,看起来像HMRC开源了一个非常有用且易于使用的图书馆,专门用于条件播放映射:https://github.com/hmrc/play-conditional-form-mapping

答案 1 :(得分:0)

您可以使用verifying的{​​{1}}方法。这将允许您在表单成功绑定到类之后创建约束,您可以在其中访问其他字段。它接受错误消息和布尔函数,这将在Mapping时向表单添加错误。

false

答案 2 :(得分:0)

我最后的解决方案是:

  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)))
      }
    )
  }