原答案
这似乎有点过于复杂了。无需手动分配值。通常你会这样写一个转发器:
@helper.repeat(form1("input"), min = 3) { fld =>
@helper.inputText(fld, '_label ->"input")
}
在函数式编程中,这就是所谓的higher-order function。您可能知道其他 scala 内置了高阶函数,例如 map、filter 或 foreach。 @helper.repeat 与 foreach 非常相似。 form1("input") 指的是要显示的值的集合。 min = 1 告诉转发器至少显示一个字段。最后,在 { fld => ... } 中,您遍历集合中定义的所有值。
换句话说:{ fld => ... } 只是一个匿名函数,它接受单个 Field 参数 (fld) 并显示该特定字段的文本输入。
跟进
好的,我正在尝试跟进您来自 cmets 的问题。让我们从helper.repeat 的签名开始。这里没有魔法,它只是一个普通的 Scala 函数:
helper.repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html]
在 Scala 中,函数可以有多个参数列表。这里我们有两个。第一个参数列表有两个参数:field 和 min。第二个参数列表将单个函数作为参数:fieldRenderer。 fieldRenderer 本身再次接受一个参数 (fld) 并返回 Html。
重要的是,您传递的不是“数据”而是一个函数。要清除它:
签名fieldRenderer: (fld: Field) => Html
等于def fieldRenderer(fld: Field): Html
这意味着,你可以在这个函数中做任何事情,只要它返回 Html。这正是最上面的示例中发生的情况。您传递Field 并返回Html。你可以通过调用@helper.inputText来做到这一点。
现在repeat 首先从field 获得一个List[Field],作为第一个参数传递。此列表对应于您的容器类的字符串列表。此外repeat 确保该列表中至少有一个元素。这是因为您将1 传递为min。然后将函数fieldRenderer 应用于我们列表中的所有元素。
repeat 的伪代码实现可能如下所示:
def repeat(field: Field, min: Int)(fieldRenderer: (fld: Field) => Html): Seq[Html] {
val list: List[Field] = field.getFields
var output: List[Html] = List()
for (i = 0; i < list.length; i++) {
val element: Field = list.get(i)
val html: Html = fieldRenderer(element)
output += html
}
return output
}