gpt4 book ai didi

forms - 没有泛型的嵌套对象支持 : workarounds

转载 作者:行者123 更新时间:2023-12-04 05:36:08 25 4
gpt4 key购买 nike

由于 Play 模板层缺乏泛型支持,因此遇到了 catch 22 的情况。

我有几个购物车屏幕,它们都需要一个用户和一个付款 + 可选的自定义字段。

case class Conference(
user: User,
payment: Payment
... custom fields here
)

因此,我没有按照购物车模型复制所有用户和付款表单字段,而是按照上述方式进行整合并实现嵌套表单。

现在,问题出现在模板层,目前还没有泛型支持。

父/容器表单引入嵌套的子表单,如下所示:
@(_form: Form[Conference])

@user.nested( UserForm.form.fill(_form.get.user) )
@payment.nested( PaymentForm.form.fill(_form.get.payment) )

然后子用户表单看起来像:
@(_form: Form[User])

@inputText(_form("user.firstName"), '_label-> "First Name*", 'class-> "required")
@inputText(_form("user.lastName"), '_label-> "Last Name*", 'class-> "required")
...

和用户模型:
case class User(firstName: String, lastName: String ...)

当 User 模型中没有 user 属性时,如何访问“user.firstName”、“user.lastName”等? Play Form申请方法是:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))

基本上它会寻找属性(property) data.user.firstName这显然是行不通的。

我想过在 User 模型中添加一个 user 属性:
case class User(firstName: String, lastName: String ...) {
val user: User
}

但不确定这是否会起作用和/或对案例类伴随对象应用/取消应用造成严重破坏。

无论如何,鉴于缺乏泛型,问题的可行解决方案是什么?

如果支持泛型,我们可以传入一个上限,一切都会好起来的:
trait CartOrder {
user: User,
payment: Payment
}
case class Conference(...) extends CartOrder

然后嵌套的用户表单被传递一个包含用户属性的实例,我们很好
@[T <: CartOrder](_form: Form[T])
@inputText(_form("user.firstName"), '_label-> "First Name*", 'class-> "required")
...

最佳答案

如果类型安全不是问题( Form 并不是所有类型安全的开始),您可以使用 Form[_]作为嵌套模板的参数类型。

如果您确实想要类型安全,一种选择是为 Form 制作一个协变的包装类,并使用它来代替 Form。一种实现是:

package views.html

import play.api.data._
import play.api.libs.json.JsValue

object FormView {
implicit def formToFormView[A, T >: A](form: Form[A]): FormView[T] = new FormView[T] {
type F = A
def realForm = form
}
}

trait FormView[+T] {
type F <: T

def realForm: Form[F]

def apply(key: String): Field = realForm(key)

def constraints : Map[String, Seq[(String, Seq[Any])]] = realForm.constraints

def data: Map[String, String] = realForm.data

def error(key: String): Option[FormError] = realForm.error(key)

def errors(key: String): Seq[FormError] = realForm.errors(key)

def errors: Seq[FormError] = realForm.errors

def errorsAsJson: JsValue = realForm.errorsAsJson

def get: T = realForm.get

def formats: Map[String, (String, Seq[Any])] = realForm.formats

def globalError: Option[FormError] = realForm.globalError

def globalErrors: Seq[FormError] = realForm.globalErrors

def hasErrors: Boolean = realForm.hasErrors

def hasGlobalErrors: Boolean = realForm.hasGlobalErrors

override def hashCode: Int = realForm.hashCode

def mapping: Mapping[F] = realForm.mapping

def value: Option[T] = realForm.value
}

现在,而不是您的模板
@(_form: Form[CartOrder])

由于不变性而不起作用,您可以使用
@(_form: FormView[CartOrder])

你可以简单地传入任何 Form[T]哪里 TCartOrder 的子类型喜欢
@user.nested(_form)

隐式将处理从 Form 到 FormView 的转换

可以在以下位置找到完整示例: https://github.com/thatsmydoing/formtest

关于forms - 没有泛型的嵌套对象支持 : workarounds,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11903593/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com