On software, computers, and video games

enriquein's blog – Opinions are my own and do not reflect the opinions of my employers, clients, parents, kids, or wife.

Making HTML helpers for Play 2 a la ASP.Net MVC

While working on my proof-of-concept web app, I first sought out to create some sort of shorthand helper to make it more wrist friendly to add CSS or Javascript files to the view.

Since all views in Play 2 are compiled into Scala functions, we can take advantage of them for this purpose. At the time of this writing their online docs only have one example, and it was very confusing for me to understand at first.

My goal was to end up with a main view similar to this:

@(title: String, scripts: Html = Html(""), styles: Html = Html(""))(content: Html)

<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
    @css("main.css")
    @script("main.js")
  </head>
  <body>
    @content
  </body>
</html>

My first stab at the problem was to create a subdirectory under views called tags, and there create a file called script.scala.html. The first iteration looked like this:

@(name: String) 
<script src="@routes.Assets.at("javascripts/@name")" type="text/javascript"></script>

Which resulted in:

<script src="/assets/javascripts/@name" type="text/javascript"></script>

I was expecting the src attribute to contain “/assets/javascript/main.js”, but it seems like it didn’t substitute the @name variable at all! After some tinkering and asking in StackOverflow I found out that my error was in assuming that I needed to prefix all of my variables with @. You see, once the parser sees the first @ in @routes.Assets.at(…) we’re in programming-land and variables are able to be referenced by name. A quick little fix now:

<script src="@routes.Assets.at("javascripts/" + name)" type="text/javascript"></script>

And now we get the correct output:

<script src="/assets/javascripts/main.js")" type="text/javascript"></script>

All we need to do now to be able to use this helper tag inside any view template is to add @import tags._ at the top of the file, but below the view parameter definitions. Here’s how the main.scala.html file looks like now:

@(title: String, scripts: Html = Html(""), styles: Html = Html(""))(content: Html)
@import tags._
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
    @css("main.css")
    @script("main.js")
  </head>
  <body>
    @content
  </body>
</html>

Leave a comment