2014-12-03 68 views
0

我有嵌套值的複雜的對象,它看起來像這樣:如何在Play框架表單中將輸入文本映射到序列中?

case class Gateway(RouteConfig: RouteConfig, gwType: Boolean, smmpp: Option[ConfigSMPP], modem: Option[ConfigModem]) 

每個對象都有無論是在smmpp或在調制解調器部件值。然後在我的嵌套對象中有一個列表成員。我基於Play文檔逐步編寫了表單映射。

val gatewayForm: Form[SmsGateway] = Form(
    mapping(
     "smsRouteConfig" -> mapping(
     "oracleId" -> optional(longNumber), 
     "smsType" -> optional(seq(text)), 
    )(RouteConfig.apply)(RouteConfig.unapply), 
     "gwType" -> boolean, 
     "smmpp" -> optional(mapping(
     "nodeId" -> optional(text), 
     "systemType" -> optional(text), 
    )(ConfigSMPP.apply)(ConfigSMPP.unapply)), 
     "modem" -> optional(mapping(
     "nodeId" -> optional(text), 
     "mdType" -> optional(text), 
    )(ConfigModem.apply)(ConfigModem.unapply)) 
    )(SmsGateway.apply)(SmsGateway.unapply) 
) 

但現在我有一些問題:

1)調制解調器或SMPP形式必須顯示,如果他們具有值或取決於gwType布爾值(0-SMPP,1-調制解調器)。我不知道該怎麼做。

2)嵌套序列必須以單個字符串格式顯示,而不是重複輸入框。例如,如果我在sq中有3個值的smsType - 我應該看到一個文本框,其中有3個值用空格或逗號分隔,並且在從文本框中提交值後,他們必須再次轉換爲seq。 我希望有人能告訴我如何去做或幫助我理解我應該做什麼,如果我的願望是不真實的。對不起,我的英語不好。

回答

3

Ad1。由於gwType不是可選字段,因此可以根據該字段的值顯示其中一個可選表單。檢查調制解調器或smpp之一是否有值是不需要的。 gwType提供了足夠的信息。

Ad2。使用映射方法的最後兩個參數完成html請求和基礎表單對象之間的自定義映射。如果映射很簡單,我會說一對一的,你通常使用生成的案例類applyunapply方法,就像你在你的例子中。由於必須將基本文本輸入映射爲字符串序列,因此需要手動解析,因此必須編寫自己的應用和不應用方法。

由於您的表單模型非常複雜,因此我發佈了更簡單的示例,以便您更輕鬆地掌握這個想法。

讓我們把它作爲我們的模型對象。

case class Entity(stringSeq: Seq[String], int: Int) 

在我們只想有兩個文本輸入如下視圖模板:

<form action="..." method="post"> 
    Strings <input name="stringSeq"><br> 
    Int <input name="int"><br> 
    <button type="submit" value="submit">Send</button> 
</form> 

所有我們需要做的是編寫自定義表單映射應用和不應用方法:

val form = Form[Entity](
    mapping(
    "string" -> nonEmptyText, 
    "int" -> number 
)((string, int) => { 
    val seq = string.split(",").toSeq 
    Entity(seq, int) 
    })((form) => { 
    val string = form.stringSeq.mkString(",") 
    Option((string, form.int)) 
    }) 

) 

而不是生成Entity.apply我們編寫一個自定義函數,將原始請求參數元組轉換爲我們的域對象。它負責將提供的字符串拆分爲一系列字符串。在第二種自定義方法中,我們做了相反的事情,即將一個序列的項再次放入單個字符串中,並返回一個元組,其中包含從我們的模型對象中取得的值。

這個例子應該爲您提供足夠的信息如何解決您的問題。

TL;博士

爲了使您的代碼更乾淨,而不是寫這些功能匿名你可以明確地定義它們。

object EntityForm { 

    val form = Form[Entity](
    mapping(
     "string" -> nonEmptyText, 
     "int" -> number 
    )(formTupleToEntity)(entityToFormTuple) 

) 

    private def formTupleToEntity(string: String, int: Int): Entity = { 
    val seq = string.split(",").toSeq 
    Entity(seq, int) 
    } 

    private def entityToFormTuple(entity: Entity) = { 
    val string = entity.stringSeq.mkString(",") 
    Option((string, entity.int)) 
    } 

} 
+0

如果我明白我們只是覆蓋我的實體的apply和unapply函數。我可以在我的伴侶對象中爲清晰的代碼做到這一點,或者我只能在映射中進行這種轉換嗎? – mechanikos 2014-12-03 10:42:15

+0

'映射'方法有兩個函數作爲參數,所以只要您正確傳遞它們,您就可以在任何地方定義它們。這只是一個簡單的例子。如果我是你,我不會在實體伴侶中重寫'apply'和'unapply',而是讓這些方法更貼近表單,因爲它們的功能與表單強烈相關,而不與實體本身相關。 – 2014-12-03 10:51:23

+0

你可以添加一些例子如何將這種轉換提取到apply \ unaply方法的其他地方,因爲我的大腦不能理解這是如何做到這一點? – mechanikos 2014-12-03 12:35:17

相關問題