Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Validation 播放验证-带有特定字段错误的自定义表单字段验证_Validation_Scala_Playframework 2.0 - Fatal编程技术网

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

Validation 播放验证-带有特定字段错误的自定义表单字段验证,validation,scala,playframework-2.0,Validation,Scala,Playframework 2.0,对于无效的美国或加拿大邮政编码,上述邮政编码表单验证工作正常,表单上显示全局错误 我希望将错误显示为字段旁边的字段错误,而不是显示在表单顶部的全局错误 有没有办法使用内置的表单约束或验证方法来实现这一点,而不是使用FormError 定义错误就像在表单中创建FormError(“,“无效邮政编码!”)对象一样,因为它没有键(第一个参数),所以框架不会将错误附加到表单元素 表单错误将请求绑定到表单时,必须创建一个新表单,删除FormError(“,”无效邮政编码!”),并将其替换为错误FormEr

对于无效的美国或加拿大邮政编码,上述邮政编码表单验证工作正常,表单上显示全局错误

我希望将错误显示为字段旁边的字段错误,而不是显示在表单顶部的全局错误


有没有办法使用内置的表单约束或验证方法来实现这一点,而不是使用FormError

定义错误就像在表单中创建
FormError(“,“无效邮政编码!”)
对象一样,因为它没有键(第一个参数),所以框架不会将错误附加到表单元素

表单错误将请求绑定到表单时,必须创建一个新表单,删除
FormError(“,”无效邮政编码!”)
,并将其替换为错误
FormError(“form.id”,“message”)

在我们的项目中,我们为表单创建了一个隐式定义来替换表单错误(我们找不到创建动态约束验证的方法)。我们有两个定义:

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
    }
}    
我们在一个名为
FormCryptBind
的类中有这些函数(因为我们还使用一些加密的东西改进了form对象),我们定义隐式定义如下:

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
定义,就像它们是表单的定义一样

我们这样使用它

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

由于我无法从应用程序中放入实际的实时代码,因此我稍微触碰了一下:D因此,如果复制并粘贴,则可能会出现编译错误。您可以将约束添加到字段中。然后更新validatePostal以接受由两个值组成的元组

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))
}
模板:

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

在他的验证中,他在validatePostal定义中同时使用了邮政和国家值,所以我认为这不是一个有效的解决方案。@Khanser,感谢您指出这一点。我修改了上面的代码来处理这个案子。如果他不在乎错误是否围绕着代码和控件,这是一个非常有效的解决方案:)也许可以使用约束对其进行改进,以便验证消息在约束验证中得到作用域,而不是在使用它的每个表单中。这仍然会将错误附加到postal字段,而不是postal.code字段。我在表单字段的正下方显示了错误,因为现在没有邮政字段的表单输入,所以不会显示错误。这与我在问题中提到的情况相同。您可以在posal.code字段上设置“error”属性。我在上面添加了一个示例。这也使@Khanser关于包装代码和国家的错误的声明无效。请记住,“帮助”属性不是必需的,只是想向您展示一些附加功能。
@inputText(
  addressForm("postal.code"), 
  '_label -> "Postal code",
  '_help -> "Please enter a valid postal code.",
  '_error -> addressForm.error("postal")
)