2014-06-22 52 views
4

Web應用程序中簡單的事情之一應該是從HTML表單讀取字段。 Play框架提供了Form類來驗證和映射這些答案。只要你不想做特別的事情,它就可以正常工作。Scala/Play Framework:如何在驗證前修改表單對象中的字段

我發現與

val newform = user.copy(errors = user.errors++Seq(FormError("email", "Already registered")), data = user.data + ("username"->"correctedName") 

我可以重新顯示窗體之前修改錯誤和領域。

但是如何在之前修改字段? 很高興刪除不需要的空白,將「11.05.2014」轉換爲「2014年5月11日」等等。

+0

你可以寫一個自定義的身體解析器爲您的具體形式 –

回答

4

如果你讓你的驗證規則更寬鬆您可能能夠在Form對象內做到這一點(nonEmptyText而不是email與不必要的空白電子郵件),使用transform來清理輸入,然後verifying實現實際驗證規則。這可能最終會變得非常醜陋,所以我不會繼續走這條路。

我認爲你只是一個不錯的選擇,可能會在調用bindFromRequest之前通過過濾器傳遞表單數據。假設您使用的是parse.urlFormEncodedBodyParser(您應該是),那麼request.dataMap[String, Seq[String]]

這是一個過濾器的粗略示例,但任何接受Map[String, Seq[String]]的東西都會返回一個帶有清理數據的新Map[String, Seq[String]]

def cleanUserForm(data: Map[String, Seq[String]]): Map[String, Seq[String]] = { 
    data.map{ case (key, values) => 
     if(key == "email") (key, values.map(_.replaceAll(" ", ""))) // trim whitespace from email 
     else (key, values) 
    } 
} 

然後在你的控制器,你必須在潔淨的數據明確地傳遞給bindFromRequest(通常接受一個隱含的要求):

def register = Action(parse.urlFormEncoded) { request => 
    val incomingData = request.body 
    val cleanData = cleanUserForm(incomingData) 
    userForm.bindFromRequest(cleanData).fold(
     formWithErrors => ... 
     user => ... 
    ) 
} 

val userForm: Form[User] = Form { 
    ... 
} 
+0

您的解決方案正在工作。但是我問自己,如果Scala不可改變是性能上的突破,那麼當你需要隨時複製信息而不是隻更新那些需要更新的字段時。複製一個完整的輸入結構似乎絕對矯枉過正。如果你需要做引體向上做這樣簡單的事情,那麼編程語言是否真的很好呢?也許沒有不可變的Java將是更好的選擇。 – bebo

+1

有一個權衡。使用不可變的數據結構,您可以獲得更安全,更清晰的代碼(除此之外),但有時會出現性能問題。不過,複製一個小的Map的開銷是微不足道的。即使你有一千個字段(任意大小的選擇),你仍然可以回退到可變集合進行優化。在任何情況下,針對您的問題的解決方案都不是因爲Scala語言,而是Play的設計。這不一定是「簡單」的事情。 –

+0

該解決方案也適用於我。我只是想補充一點,如果你只打算從字符串的開始/結尾修剪空格,你可以在Scala中使用'String.trim'函數。 – JayD3e