Templating Basics

In my previous blog I wrote about how to get your project set up. In this post we will cover one of the major differences between traditional JavaEE and Play, the Scala-based views.

I was completely new to Scala when I started working with Play 2.0 and it took a while to get comfortable with the change in syntax. Scala is a very concise language that can perform many common operations in fewer lines of code. There are several resources around the web that will go into greater detail when it comes to Scala.

Structure

Let's look at the basics of a view template for Play!

@(message: String)
 
@main("Welcome to Play 2.1") {
 @play20.welcome(message, style = "Java")
}

Anything with an @ in front of it is an instruction to do some replacement much like % is in JSP. The main difference here is that @main("Welcome to Play 2.1") is a function call to another view file. All view files are compiled and can be called just like a function with parameters. Any template named .scala.html will be available as a function called . You can call it whenever as long as the required parameters are specified. Let's look at our main.scala.html.

@(title: String)(content: Html)
 
DOCTYPE html>
<html>
 <head>
 <title>@title</title>
 <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
 <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
 <script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
 </head>
 <body>
 @content
 </body>
</html>

The difference between these two files is that index has one single parameter defined and main has a parameter and then a content block. The content block is the body of the call to the template so anything inside the curly braces in our index file will be passed in and rendered in place of @content. This is a major change compared to JSP and makes view composition a lot easier. With JSP you would have to use something like SiteMesh or Tiles to achieve the same structure.

Parameters

One aspect that makes development a little more time consuming is that templates must declare all parameters it uses. There is no context or page object to put arbitrary data in so it will make you really think through the design of your template structure. This brings another benefit that I wrote about in the first post. All views are compiled so you will get compile errors if your calls don't match your view parameter declarations.

You might think that having no context is a problem when passing data to a view but Scala has something called implicit parameters. What this means is that you don't have to specify the parameter for it to be accessible. In Play! this includes access to request, session, messages (I18N) and a few other things. You can add your own implicit parameters but I'm not going into that here. In my opinion, having a context an anti-pattern. With a context developers tend to throw a ton of data in there. With Play! you can reuse a template as long as the correct parameters are passed in and it will be checked at compile time! In JSP, how many developers have not tried to reuse a view only to have it fail in edge cases because of missing data? Not to mention you will not notice it until runtime where template is compiled under unpredictable conditions each time is is used.

Iterating

One of the more common things you need is iterating through a dataset and render it in some form. The scala language has a multitude of ways to do this, let's look at a the few that I use more frequently.

Regular iterating through a set of elements looks like this.

@for(element <- elements) {
 <div class="element">
 @element
 </div>
}

The elements dataset can be any type of List or Set.

Regular iterating through a set of elements with an index.

<ul>
 @for( (element,index) <- elements.zipWithIndex ) {
 <li>@index. @element</li>
 }
</ul>

Once again, the dataset can be any type of List or Set.

Iterating over a Map is just as easy.

<dl>
 @for((key, value) <- elementMap) {
 <dt>
 @key - @value
 </dt>
 }
</dl>

Now, to get really creative we can combine the map iteration with the index operation.

<dl>
 @for(((key, value), index) <- elementMap.zipWithIndex) {
 <dt>
 @index. @key - @value
 </dt>
 }
</dl>

Reusable View Fragments

With JSP you can create custom tags that take some of the redundancy out of your code. In Play!, using Scala there are several ways to create reusable fragments. Let's look at them in order of complexity.

Inline

Creating an inline fragment is as easy as defining a method, it would look something like this.

@heading(title:String) = {
 <div class="heading">
 <h2>@title</h2>
 </div>
}

And then you call your new function in the same way you would call a different template.

@heading("Welcome!")

This reduces the redundant code in your templates substantially.

Separate Template

But what if you wanted to reuse your new heading in other views? All you need to do is create a separate file and copy the heading function to that file. Instead of the function declaration, you declare it almost like you would a normal template. The difference is that you can include the second set of parentheses and include a body or you can leave it out. A simple fragment without body would look like this.

@(title:String)
<div class="heading">
 <h2>@title</h2>
</div>

A slightly more advanced version of this fragment would look like this.

@(title:String)(body:Html)
<div class="heading">
 <h2>@title</h2>
 <div class="text">
 @body
 </div>
</div>

This fragment also requires a body that would be passed in by the calling template.

@_heading("Welcome!"){
 Lorem ipsum.
}

The leading _ is not necessary it's just something I do to indicate that this is a fragment.

Separate Action

Any time you need to do more advanced operations you would probably want to do that outside of a template. You can do that by adding a static method to any class.

public static Html getRssFeed(String title, String url) {
 List<String> list = … get RSS feed from url
 return _feed.render(title, list);
}

Your _feed.scala.html template would be just like any other template. Remember to make your method static or you will get a compile error.

@(title:String, elements:List[String])
 
@_heading(title) {
 @for(element <- elements) {
 <div class="element">
 @element
 </div>
 }
}

Notice how you can do anything you can do in a normal template, including calling our previous template _heading.scala.html to keep a consistent look throughout.

Calling our method is no harder than calling another template.

@Application.getRssFeed("Feed", "http://rss.cnn.com/rss/cnn_topstories.rss")

Partially Applied Templates

Another feature with Scala is partially applied functions, which you can take advantage of in your templates. A partially applied function is a function where you pass in some of the parameters the function requires but not all.

@(message: String)
 
@main("Welcome to Play 2.1") {
 @defining(Application.getRssFeed("Feed", _:String)) { feed =>
 
 @_heading("Welcome!"){
 Lorem ipsum.
 }
 
 @feed("http://rss.cnn.com/rss/cnn_topstories.rss")
 
 @feed("http://rss.cnn.com/rss/money_latest.rss")
 }
}

This example is a bit contrived but it shows how easy it is to create a partially applied function. The _ tells the compiler that this is a partially applied function and what type it is supposed to be. This also shows how to define a variable in your template. Adding @defining(...) { name => ... } will make anything inside the parentheses defined as name within the scope of the curly braces.

A little more complex example would be to pass a partially applied template from one template to another. Lets update our main.scala.html template.

@(title: String, template:String => (Html => Html))(content: Html)
 
DOCTYPE html>
 
<html>
 <head>
 <title>@title</title>
 <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
 <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
 <script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
 </head>
 <body>
 @template("Clever Heading") {
 Magis lorem ipsum
 }
 
 @content
 </body>
</html>

If you look at the template parameter definition you will see that we have defined a parameter named template that takes a string parameter and a body of Html and then returns Html.
Calling our main template would look like this.

@main("Welcome to Play 2.1", _heading(_)_) {
 @_heading("Welcome!"){
 Lorem ipsum.
 }
}

Here we are telling our main template that the title parameter will be "Welcome..." and that our template parameter will be our previously created _heading template. We are also telling our main template that this template has a parameter defined but that we are not passing it in by adding the _. The _ without the type tells the compiler that it should expect whatever the main template has defined. Scala infers all types if it can do so.

Summary

Play! Framework's view technology is very flexible. All views are compiled when your application starts up or you can do it manually. Since they are compiled they offer other benefits, as I noted in my earlier post they can be unit tested. No context or server needed, just a simple unit test.

In my next blog I will write about routing and asset management, something Play! does a bit differently than most other Java based web frameworks.