2014-03-18 36 views
1

使用播放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) 
) 

我想補充驗證,這樣,如果_type ==「買賣」,然後換來的是必填字段,但如果_type ==「let」then expectedMoveIn是必填字段。我似乎找不到用標準遊戲驗證器來做到這一點的方法,有沒有辦法做到這一點?

乾杯 尼克

回答

0

您可以使用Mappingverifying方法。這將允許您在表單成功綁定到類後創建約束,您可以在其中訪問其他字段。它接受錯誤消息和一個布爾函數,當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 
) 
) 
+0

啊是的,我做了這個,但問題是,結果錯誤將不會綁定到該字段,它只會在表單級別。我需要在隨後的演示文稿中將該字段標記爲無效。可能嗎? – nfvindaloo

+1

與表格映射,似乎並不如此。表單字段在彼此綁定之前並不知道對方的任何內容。當驗證依賴於這樣的多個字段時,錯誤是否應該被綁定到一個呢?如果你真的想這樣做,看起來你必須在窗體外部驗證你的對象(一旦它被綁定),並使用'withError'自己添加錯誤。 http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.data.Form –

+0

我需要這樣做的原因是,我的表單,因此我的dto是多層次的,目的,並映射到兩個案例類之一。在我嘗試做到這一點之前,我需要驗證它會將映射確定(基於_type)。所以我認爲有必要這樣做,正如你所建議的那樣,儘管在控制器中使用手動調用看起來像現在的方式。謝謝! NFV – nfvindaloo

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