5

In my Play HTML template inside my custom module, I have the following line of code:

<script type="text/javascript" src="@controllers.core.routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))"></script>

This references a WebJarAssets class in the core module that looks like this:

package controllers.core

import javax.inject._
import play.api.http.HttpErrorHandler
import play.api.{Environment, Configuration}

class WebJarAssets @Inject()(errorHandler: HttpErrorHandler, configuration: Configuration, environment: Environment) extends controllers.WebJarAssets(errorHandler, configuration, environment)

Please note that I have also included the following line in build.sbt in the custom module:

"org.webjars" %% "webjars-play" % "2.5.0",

When starting the application, I receive the following error:

[error] /Users/john/DemoProject/modules/custom/app/views/custom/templates/main.scala.html:36: not found: value WebJarAssets
[error]     <script type="text/javascript" src="@controllers.core.routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))"></script>
[error]                                                                                  ^

Judging from the implementation of WebJarAssets in earlier releases, there was no need to implement and inject an own controller for this (for example, see this tutorial).

What am I doing wrong? Do I even need a WebJarAssets class for this (as I need web jar assets in many modules, I added this for now in the core module). Furthermore, why do I need to manually inject it in the template and why is it not automatically resolved?

In case you wonder what manually inject means for me:

@(title: String, webJarAssets: WebJarAssets)(content: Html)(implicit messages:Messages)
<script type="text/javascript" src="@controllers.core.routes.WebJarAssets.at(webJarAssets.locate("jquery.min.js"))"></script>
John Doe
  • 275
  • 2
  • 12

3 Answers3

7

Before webjars-play 2.5.0 there was a static method that you could use in your templates. Since Play has been moving away from global state / static methods, that was removed from webjars-play and now you need to inject WebJarAssets. Unfortunately the Twirl templates don't support injection yet. So you have to inject it into your controller and then pass it to your template. Here is a full sample app that does this: https://github.com/webjars/webjars-play/tree/master/test-project

James Ward
  • 28,966
  • 9
  • 47
  • 79
  • 1
    Thank you for your explanation. However, I think this new approach introduced [circular dependency issues](http://stackoverflow.com/questions/37057137/how-to-prevent-circular-dependencies-when-using-webjarassets-play-2-5). – John Doe May 05 '16 at 17:54
  • 2
    I don't like this approach. This is degradation. – Bob Aug 09 '16 at 11:45
  • @KhwarezmShah Can you file an issue on https://github.com/webjars/webjars-play with more details? – James Ward Aug 09 '16 at 13:50
  • @JamesWard Yes, sure – Bob Aug 10 '16 at 03:39
  • If I understand correctly, this means that during migration to 2.5 most likely every single controller and view will have to be updated with this parameter. :( – wwkudu Aug 24 '16 at 05:44
  • Is there any view on if and when Twirl will support injection? – wwkudu Aug 24 '16 at 05:45
  • 1
    It looks like it is supported now: https://github.com/playframework/twirl/pull/100 – James Ward Aug 24 '16 at 14:56
2

It can write like that.

controller:

class Application @Inject()(implicit webJarAssets: WebJarAssets,
                          val messagesApi: MessagesApi, materializer: Materializer)
  extends Controller with I18nSupport {

template:

@(title: String)(content: Html)(implicit messages: Messages, webJarAssets: WebJarAssets)
<script type='text/javascript' src='@routes.WebJarAssets.at(webJarAssets.locate("jquery.min.js"))'></script>
Hossshy
  • 31
  • 2
1

As @james-ward said in play-2.5.12 with twirl-1.2.0 you can declare inject dependencies in templates but they will become classes and not objects that complicates the reference to the templates from other ones.

The changes are:

project/plugins.sbt

addSbtPlugin("com.typesafe.sbt" % "sbt-twirl" % "1.2.0")

main.scala.html

@this(webJarAssets: WebJarAssets)

@(title: String)(content: Html)(implicit messages:Messages)
<script type="text/javascript" 
  src="@controllers.core.routes.WebJarAssets.at(webJarAssets.locate("jquery.min.js"))">
</script>

Note that a caller of the main template should also declare a constructor mainClient.scala.html:

@this(mainRef: main)
@(...)

content
@main("title"){   }
content
raisercostin
  • 7,909
  • 3
  • 58
  • 68