I’m a swiss Master student in Computer Science. I’m very interested in C++, open source projects, Linux, Intel Assembly and Agile. I'm currently working on Eddi, a new programming language that I created to improve my skills in C++. I've also worked a lot on Java technologies (Sprint, Osgi, Play!, ...), but I'm not currently working with Java anymore. Baptiste is a DZone MVB and is not an employee of DZone and has posted 51 posts at DZone. You can read more from them at their website. View Full User Profile

Play Framework – The Template Engine

07.20.2010
| 8815 views |
  • submit to reddit

In my previous post about the Play Framework, we've seen how to install Play and create a first simple application. In this post, we’ll see how to customize the views and use the template engine of the framework to easily create web pages.

Play has its own template engine to generate HTML web pages. The template engine use Groovy as it's expression language. You will use the Groovy language to create all the dynamic parts of the web pages. But there is no need to completely learn Groovy; it’s really close to Java and if you know already know Java, it's  no problem to use Groovy in your templates. All the templates are located in the app/views folder in your application. All the dynamic parts of the web page are resolved during the execution of the template and the result is part of the HTTP Response.

So first of all, we’ll create a little application for our needs :

wichtounet@wichtounet-laptop:~/dev/play$ /usr/share/play/play new views
~        _            _
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/
~
~ play! 1.0.3, http://www.playframework.org
~
~ The new application will be created in /home/wichtounet/dev/play/views
~ What is the application name? Views
~
~ OK, the application is created.
~ Start it with : play run views
~ Have fun!
~

So we'll start to inspect what has been created by Play. If you go in app/views, you will see this structure :

  • Application : This folder is to store the templates of the Application controller
  • errors : This folder contains the templates for the HTTP Error pages (404, 500, …)
  • main.html : This is the main template

If you open Application/index.html, you get this kind of code :

#{extends 'main.html' /}
#{set title:'Home' /}
 
#{welcome /}

The first line indicates that we extend another template (main.html). The next line uses a Play tag (set), to set the title of the page. A set tag has a brother, the get tag who get the value setted by the set tag. The last line uses the welcome tag which prints the content of the welcome page.

Now, let’s see the main.html template :

<!DOCTYPE html>

<html>
<head>
<title>#{get 'title' /}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" media="screen" href="@{'/public/stylesheets/main.css'}">
#{get 'moreStyles' /}
<link rel="shortcut icon" type="image/png" href="@{'/public/images/favicon.png'}">
<script src="@{'/public/javascripts/jquery-1.4.2.min.js'}" type="text/javascript" charset="utf-8"></script>
#{get 'moreScripts' /}
</head>
<body>
#{doLayout /}
</body>
</html>

There are some interesting things here :

  • #{get ‘title’ /} : returns the value of the variable title (not a Java variable, only a HTML variable)
  • @{‘/public/stylesheets/main.css’} : resolve the resource to its URL
  • #{doLayout /} : Indicates where the sub templates (template who extends main.html) will be rendered

Pass variables to the view

So let’s go further. The first important thing is to know how to pass variables to the view from the controller. With the Play Framework, this is really simple. Just add the variables you need to the render() method of the controller. For example, to pass a String to the view :

package controllers;

import play.mvc.*;

public class Application extends Controller {
public static void index() {
String hello = "Hello World from Controller !";

render(hello);
}
}

The variable hello is now accessible from the view on the name “hello”. To get it, you have to use ${variable_name} simply to display it :

#{extends 'main.html' /}
#{set title:'Home' /}

Hello from the view
<br />
${hello}

Easy, no ?

Let’s try adding a simple class to our model :

package models;

public class Book {
private final String title;

public Book(String title) {
super();

this.title = title;
}

public String getTitle() {
return title;
}
}

And pass it to the view :

    public static void index() {
Book book = new Book("Hello Play !");

render(book);
}

And then get it from the view :

#{extends 'main.html' /}
#{set title:'Home' /}

Hello from the view
<br />
I've a book for you "${book.title}".

The property is retrieved using the JavaBeans convention, so you have to create a getTitle() method to get the title of the book.

All the dynamic content is directly escaped by the template engine to avoid XSS security exploits. If you really want to avoid escaping something, you have to use the raw() method available on all the strings. For  example, for our title :

${book.title.raw()}

But this is not a really good practice, and must be used only when it’s necessary.

You can add comments to your templates if you want :

*{Will not be evaluated by the template engine}*

Iterate over a list

An important thing to do in template is to iterate over a collection. For example, we can pass a list of books to the view from the controller :

   public static void index() {
List<Book> books = new ArrayList<Book>(3);

books.add(new Book("Hello Play !"));
books.add(new Book("Hello Template !"));
books.add(new Book("Hello Engine !"));

render(books);
}

And then, you can iterate over the list using the list tag :

#{extends 'main.html' /}
#{set title:'Home' /}

I've some books for your :

<ul>
#{list items:books, as:'book'}
<li>${book.title}</li>
#{/list}
</ul>

And that will display a single little list in our web page. Not too complicated :)

Using scripts

If you have to make complicated things, you can use scripts in Groovy. With scripts, you can declare variables and use all the other variables. For example, you can make the title upper case in a script :

#{extends 'main.html' /}
#{set title:'Home' /}

I've some books for your :

<ul>
#{list items:books, as:'book'}
%{
bookTitle = book.title.toUpperCase();
}%
<li>${bookTitle}</li>
#{/list}
</ul>

But you can also do iterations, conditions and a lot of other things. But keep in mind that templates are not a good place to make complicated things, for that you have the controller and the models. The template must be as simple as possible.

Define tags

There is lot of tags in Play Framework, but you can create your own tags. For that, you just have to create a tags folder in your views folder. For example, if you create booklist.html in views/tags and add the following code :

<ul>
#{list items:_items, as:'book'}
%{
bookTitle = book.title.toUpperCase();
}%
<li>${bookTitle}</li>
#{/list}
</ul>

The arguments are obtained using ‘_’ following by the name of the arguments (_items in our example).

You can refactor the template index.html using the new tag :

#{extends 'main.html' /}
#{set title:'Home' /}

I've some books for your :

#{booklist items:books /}

You provide arguments like in any other tag. This can help you to make cleaner templates and to avoid to copy/paste some code.

So we’ve now covered the basis of the template engine of Play Framework. With all that we’ve seen, we can start to create simple Play Applications.

A really good resource for Play developers is the Play Cheat Sheet. You can also consult the official documentation for more complete information.

From http://www.baptiste-wicht.com/2010/07/play-framework-template-engine

Published at DZone with permission of Baptiste Wicht, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Matthew Welch replied on Tue, 2010/07/20 - 9:50am

The property is retrieved using the JavaBeans convention, so you have to create a getTitle() method to get the title of the book.

The model used in this example does not take advantage of one of Play!'s best usability and efficiency features:

http://www.playframework.org/documentation/1.0.3/model#properties

See the section on properties simulation. I intially was quite skeptical of this feature, but it's more sophisticated than it might seem on the surface and works almost flawlessly once your used to it. If you need a more tangible accessor that manipulates the attribute before returning it, you can create one, but if you don't then your code isn't muddied by the triviality of an accessor. In both cases, Play! does the right thing.

Consider this model:

public class Book {
  public String title;

  public Book(String title){
   this.title = title;
  }
}

Play! will generate a getter and setter for you and every time in your code (your real java code, not just your templates) where you write "book.title", you will actually be calling "book.getTitle()" at runtime. Consider this second model:

public class Book {
  public String title;

  public Book(String title){
    this.title = title;
  }

  public getTitle(){
   return title.toLowerCase();
  }
}

Again, every time in your code when you write "book.title" you will be calling "book.getTitle()", but instead of a generated getter, it will be the one you wrote. It was this second sitaution that initially threw me a curve when I first worked with Play!. I didn't realize that even normal java code would be modified at runtime to always call the generated or written getter. Because of this, despite the fact that the attribute is "public", it is still entirely encapsulated while retaing the ease of use and clean presentation of a public attribute when writing code.

It's initially a little weird for long time Java developers like myself, but it was suprisingly easy to get used to and now I cringe a little when working on code that doesn't use Play! as I'm forced to write hundreds of accessors.

Baptiste Wicht replied on Tue, 2010/07/20 - 10:35am in response to: Matthew Welch

Really interesting, thanks :) I didn't know that even your normal code will be replaced with call to setters and getters. It's quite a good solution. Thanks a lot.

Rehman Khan replied on Sat, 2012/02/25 - 4:20am

I have been exploring on the internet trying to find some ideas on how to get our web site coded, your current style and theme are wonderful. Did you actually code it yourself or did you get a programmer to do it to suit your needs?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.