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?
3 solutions:
First
Typpicaly for partial templates you should use
tagsas described in the docs, whereapp/views/tagsfolder is a base:file:
app/views/tags/product.scala.htmlin the templates (no initial import required in the parent view full syntax will allow you to avoid name-clash:
@tags.packageName.tagName()):Of course in your case you can also use packages in the base folder
file:
app/views/tags/item/product.scala.htmlI’m pretty sure that’ll solve your problem.
Second
To avoid clash without changing package’s name you can just rename the
itemin your view, also I recommend do not use aformname for the Form[T] as it can conflict with helpers:Third
If you’ll fill your
Form[Item]before passing to the view with givenItemobject, you don’t need to pass both, as most probably you can get data from the form:Of course in you product.scala.html you’ll need to change the
@(item: Item)param to@(itemForm: Form[Item])