2012-03-17 48 views
2

我有鑑於登錄表單,有一個name輸入有許多驗證:如果一個表單域有多個驗證器,如何讓它們逐個驗證,而不是全部?

object Users extends Controller { 

    val loginForm = Form(tuple(
     "name" -> ( 
      nonEmptyText // (1) 
      verifying ("Its length should >= 4", name=>{ println("#222");name.length>=4 }) // (2) 
      verifying ("It should have numbers and letters", name=>{println("#333"); ...}) // (3) 
     ) 
} 

然後我不輸入任何東西,按提交,我發現控制檯打印:

#222 
#333 

這意味着所有的驗證進行,並且他們有關係:

(1) & (2) & (3) 

但我希望他們:

(1) && (2) && (3) 

這意味着,如果名稱爲空,後面的兩個驗證器將被忽略。

play2有可能嗎?

回答

5

默認行爲是應用在字段上定義的所有約束。 但是,您可以定義自己的驗證約束停在第一個失敗將約束:

def stopOnFirstFail[T](constraints: Constraint[T]*) = Constraint { field: T => 
    constraints.toList dropWhile (_(field) == Valid) match { 
    case Nil => Valid 
    case constraint :: _ => constraint(field) 
    } 
} 

可以使用如下所示:

val loginForm = Form(
    "name" -> (text verifying stopOnFirstFail(
    nonEmpty, 
    minLength(4) 
)) 
) 
scala> loginForm.bind(Map("name"->"")).errors 
res2: Seq[play.api.data.FormError] = List(FormError(name,error.required,WrappedArray())) 

scala> loginForm.bind(Map("name"->"foo")).errors 
res3: Seq[play.api.data.FormError] = List(FormError(name,error.minLength,WrappedArray(4))) 

scala> loginForm.bind(Map("name"->"foobar")).errors 
res4: Seq[play.api.data.FormError] = List() 

(請注意,我實現stopOnFirstFail適用兩次失敗約束,所以這一個不應該有副作用)

+0

請參閱我的相關問題:http://stackoverflow.com/questions/97 59660 /如何對限定-A-stoponfirstfail-DSL換play2s形式 – Freewind 2012-03-18 15:47:28