Play/Scala模板中的参数和视图命名冲突

Play/Scala模板中的参数和视图命名冲突,scala,playframework,playframework-2.0,Scala,Playframework,Playframework 2.0,我不熟悉这个框架,仍然在尝试使用新的Scala模板引擎来解决一些问题 假设我有以下包结构: app/ app/controllers/Items.scala app/models/Item.scala app/views/layouts/page.scala.html app/views/item/show.scala.html app/views/item/details.scala.html //partial 这是我的项目/展示模板: @(item: Item, form: F

我不熟悉这个框架,仍然在尝试使用新的Scala模板引擎来解决一些问题

假设我有以下包结构:

app/
app/controllers/Items.scala
app/models/Item.scala
app/views/layouts/page.scala.html
app/views/item/show.scala.html
app/views/item/details.scala.html  //partial
这是我的项目/展示模板:

    @(item: Item, form: Form[Item])(implicit flash: Flash)
    @layout.page() {
        @*want to include details partial, wont work due to item param*@
        @item.details(item)
    }
由于包含另一个模板(例如,上面包含项/详细信息)的语法与访问模板参数(例如,上面的项)的语法完全相同,显然,如果不做一些更改,现有的命名约定将无法工作

我知道我可以将我的“app.views.item”包重命名为“app.views.items”,并依靠单数/复数形式将视图与参数名称区分开来,但这似乎不是一个非常简单的解决方案。如果我真的希望参数名与视图包相同,该怎么办

我的一个想法是用一个额外的顶级软件包为我的所有视图做准备:

 app/views/views/item/details.scala.html
因此,include语法应该是@views.item.details(),但这显然是一种攻击

避免这个问题的好方法是什么?如何更好地组织代码以避免此类命名冲突

大多数其他模板引擎使用“包含”或“渲染”等操作来指定部分包含。我无意冒犯这里的任何人,但Play Scala模板引擎语法是否如此简洁,以至于它实际上决定了代码的组织

3种解决方案:

弗斯特 通常,对于部分模板,您应使用所述的
tags
,其中
app/views/tags
文件夹是一个基础:

文件:
app/views/tags/product.scala.html

<div id="container">
    @tags.item.product(item)
</div>
在模板中(父视图中无需初始导入完整语法将允许您避免名称冲突:
@tags.packageName.tagName()
):

我相信这会解决你的问题

第二 为了避免在不更改包名称的情况下发生冲突,您只需在视图中重命名
,我还建议不要对表单[T]使用
表单
名称,因为它可能与帮助程序冲突:

@(existingItem: Item, existingItemForm: Form[Item])(implicit flash: Flash)
@layout.page() {
    @item.details(existingItem)
}
第三 如果在使用给定的
Item
对象传递到视图之前填写
Form[Item]
,则不需要同时传递这两个对象,因为很可能可以从表单中获取数据:

@(itemForm: Form[Item])(implicit flash: Flash)
@layout.page() {
    <div>Name of item is: @itemForm("name").value (this is a replacemnet for @@existingItem.name </div>
    @item.details(itemForm)
}
@(itemForm:Form[Item])(隐式flash:flash)
@布局。第页(){
项目名称为:@itemForm(“Name”).value(这是@existingItem.Name的替换项
@项目.详细信息(项目表格)
}

当然,在product.scala.html中,您需要将
@(item:item)
参数更改为
@(itemForm:Form[item])

可能需要使用完整的限定名:
@views.item.details(item)
我还注意到控制器和模型类名称存在类似问题。在各种示例应用程序中,我看到模型名称,如“app.models.Item”和控制器名称,如“app.controllers.Items”。通过包级导入,现在由新开发人员来确定“Item”是模型还是“Items”是一个控制器。这很有效,但我担心可能会出现混乱/可读性差。@nico_ekito,完全限定的视图名称对我不起作用。我遇到一个编译错误。我尝试了
@app.views.item.details(item)
以及
@views.item.details(item)
。有什么建议吗?正确的完全限定名称是:
@views.html.item.details(item)
。是的,我总是忘记.html;-)很好!我从来没有想到,既然一切都是一个函数,我就可以把一个包含看作是一个标记。我本来打算采用一种惯例,比如
app.views.item.includes
,但我更喜欢
app.views.tags.item
方法。我不喜欢(2),但我明白你不使用参数名“form”的观点。。。“itemForm”似乎是一个更好的称呼。(3) 工作正常,但假设我也需要Item实例,这并不能解决我原来的问题。我已经开始重构代码以使用方法(1)。
@(itemForm: Form[Item])(implicit flash: Flash)
@layout.page() {
    <div>Name of item is: @itemForm("name").value (this is a replacemnet for @@existingItem.name </div>
    @item.details(itemForm)
}