播放验证 - 具有特定字段错误的自定义表单字段验证

播放验证 - 具有特定字段错误的自定义表单字段验证

问题描述:

case class Address(
    address1: String, 
    city: String, 
    state: String, 
    postal: String, 
    country: String 
) 

Form(
    mapping = mapping(
     "address1" -> nonEmptyText, 
     "city" -> nonEmptyText, 
     "state" -> nonEmptyText, 
     "postal" -> nonEmptyText, 
     "country" -> nonEmptyText 
    )(Address.apply)(Address.unapply).verifying("Invalid Postal Code!", validatePostal _) 
) 

def validatePostal(address: Address): Boolean = { 
    address.country match { 
     case "US" | "CA" => 
     val regex: Regex = ("^(\\d{5}-\\d{4}|\\d{5}|\\d{9})$|^([a-zA-Z]\\d[a-zA-Z]()?\\d[a-zA-Z]\\d)$").r 
     regex.pattern.matcher(address.postal).matches() 
     case _ => false 
    } 
}  

以上表单验证的邮政编码工作正常,表单上显示无效美国或加拿大邮政编码的全局错误。播放验证 - 具有特定字段错误的自定义表单字段验证

我想显示错误作为字段错误在字段旁边,而不是全局错误,在我的情况是显示在窗体的顶部。

有没有一种方法可以使用内置的Form约束或验证方法来实现这一点而不是FormError?

您可以将约束添加到该字段。然后更新验证邮件以接受两个值的元组。

Form(
    mapping = mapping(
    "address1" -> nonEmptyText, 
    "city" -> nonEmptyText, 
    "state" -> nonEmptyText, 
    "postal" -> tuple(
     "code" -> nonEmptyText, 
     "country" -> nonEmptyText 
    ).verifying("Invalid Postal Code!", validatePostal _), 
)((address1, city, state, postal) => Address(address1, city, state, postal._1, postal._2))((address: Address) => Some((address.address1, address.city, address.state, (address.postal, address.country)))) 
) 

模板:

@inputText(
    addressForm("postal.code"), 
    '_label -> "Postal code", 
    '_help -> "Please enter a valid postal code.", 
    '_error -> addressForm.error("postal") 
) 
+0

在他确认他validatePostal定义同时使用邮政和国家的价值观,所以我不认为这是一个有效的解决方案。 – Khanser

+0

@Khanser,谢谢你指出。我改变了上面的代码来处理这种情况。 – dingdong

+1

如果他不关心这个错误是否包含代码和contry,那么这是一个完全有效的解决方案:)也许可以使用约束来改进它http://www.playframework.com/documentation/2.2.x/ScalaCustomValidations所以,验证消息被限制在约束验证中,而不是每个使用它的表单。 – Khanser

定义错误,就像您在窗体中创建一个FormError("","Invalid Postal Code!")对象一样,因为它没有键(第一个参数),框架不会将错误附加到表单元素。

在形式的错误时,你要绑定的请求表,你必须创建一个新的形式取出FormError("","Invalid Postal Code!")FormError("form.id","message")

在我们的项目中,我们创建了一个隐含的高清的形式,以一个错误替换它替换形式的错误(我们无法找到一个方法来创建动态约束验证)这些是2点的定义,我们有:

def replaceError(key: String, newError: FormError): Form[T] = { 
    val updatedFormErrors = form.errors.flatMap { fe => 
    if (fe.key == key) { 
     if (form.error(newError.key).isDefined) None 
     else { 
     if (newError.args.isEmpty) Some(FormError(newError.key,newError.message,fe.args)) 
     else Some(newError) 
     } 
    } else { 
     Some(fe) 
    } 
    } 

    form.copy(errors = updatedFormErrors.foldLeft(Seq[FormError]()) { (z, fe) => 
    if (z.groupBy(_.key).contains(fe.key)) z else z :+ fe 
    }) 
} 

def replaceError(key: String, message: String, newError: FormError): Form[T] = { 
    def matchingError(e: FormError) = e.key == key && e.message == message 
    val oldError = form.errors.find(matchingError) 
    if (oldError.isDefined) { 
    val error = if (newError.args.isEmpty) FormError(newError.key,newError.message,oldError.get.args) else newError 
    form.copy(errors = form.errors.filterNot(e => e.key == key && e.message == message)).withError(error) 
    } 
    else form 
} 

我们那些在一个名为FormCryptBind(类,因为我们还加强与表单对象一些加密的东西),我们定义像th一样的隐式def是:

implicit def formBinding[T](form: Form[T])(implicit request: Request[_]) = new FormCryptBind[T](form) 

我们那样做,因为刚刚导入有这种隐含定义的对象,你可以使用所有的FormCryptBind定义,因为他们窗体的

而且我们使用这样的

import whatever.FormImprovements._ 
... 
object SomeController extends Controller{ 
... 
def submit = Action{ implicit request => 
form.bindRequest.fold(
    formWithErrors => { 
    val newForm = formWithErrors.replaceError("", "formField.required", FormError("formField", "error.required") 
    BadRequest(someView(newForm) 
    }, 
    formDetails => Redirect(anotherView(formDetails)) 
} 

因为我不能从应用程序中放置实际的实时代码,所以我稍微摸了一下:D因此如果您复制&粘贴