Automatically inject WebJarAssets in Play 2.5 HTML

2019-04-08 19:34发布

问题:

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>

回答1:

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



回答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>


回答3:

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