Reputation: 1195
I am new to Play Framework and still trying to wrap my head around some things with the new Scala template engine.
Let's say I have the following package structure:
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
And this is my item/show template:
@(item: Item, form: Form[Item])(implicit flash: Flash)
@layout.page() {
@*want to include details partial, wont work due to item param*@
@item.details(item)
}
Since including another template (e.g. including item/details above) is the exact same syntax as accessing a template parameter (e.g. item above), obviously this existing naming convention won't work without something changing.
I know I can rename my "app.views.item" package to "app.views.items", and rely on singular/plural forms to differentiate the view from the param name, but this does not seem like a very straightforward solution. Also what if I really want the parameter name to be the same as the view package?
One idea I have is to prepend all my views with an extra top level package:
app/views/views/item/details.scala.html
So the include syntax would be @views.item.details(), but again this is obviously a hack.
What is a good way to avoid this issue? How can I better organize my code to avoid such naming collisions?
Most other template engines use operations like "include" or "render" to specify a partial include. I don't mean to offend anyone here, but is the Play Scala template engine syntax so terse that it actually dictates the organization of code?
Upvotes: 2
Views: 1286
Reputation: 55798
3 solutions:
Typpicaly for partial templates you should use tags
as described in the docs, where app/views/tags
folder is a base:
file: app/views/tags/product.scala.html
in the templates (no initial import required in the parent view full syntax will allow you to avoid name-clash: @tags.packageName.tagName()
):
<div id="container">
@tags.product(item)
</div>
Of course in your case you can also use packages in the base folder
file: app/views/tags/item/product.scala.html
<div id="container">
@tags.item.product(item)
</div>
I'm pretty sure that'll solve your problem.
To avoid clash without changing package's name you can just rename the item
in your view, also I recommend do not use a form
name for the Form[T] as it can conflict with helpers:
@(existingItem: Item, existingItemForm: Form[Item])(implicit flash: Flash)
@layout.page() {
@item.details(existingItem)
}
If you'll fill your Form[Item]
before passing to the view with given Item
object, you don't need to pass both, as most probably you can get data from the form:
@(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)
}
Of course in you product.scala.html you'll need to change the @(item: Item)
param to @(itemForm: Form[Item])
Upvotes: 1