Built-in template tags
These are the built-in tags that are available in addition to the core template engine syntax.
There is a separate Java extensions manual page.
a
The a
tag inserts an HTML link to a controller action.
#{a @Application.logout()}Disconnect#{/a}
Rendered as:
<a href="/application/logout">Disconnect</a>
If the action you try to call does not have any route able to invoke it using a GET method, Play will automatically generate a hidden form that will be submitted on link click using JavaScript.
authenticityToken
Renders a hidden input field containing a generated token that you can use in any form, to prevent Cross-Site Request Forgery.
#{authenticityToken /}
Rendered as:
<input type="hidden" name="authenticityToken"
value="1c6d92fed96200347f06b7c5e1a3a28fa258ef7c">
cache
Caches the tag body using the play.cache.Cache
API, for the cache key specified by the tag parameter.
#{cache 'startTime'}
${new java.util.Date()}
#{/cache}
The body is cached indefinitely by default, but you can specify an expiration duration with the for
parameter.
#{cache 'currentTime', for:'3s'}
${new java.util.Date()}
#{/cache}
doLayout
Used with template inheritance, this tag inserts the evaluated sub-template’s contents.
<!-- common header here -->
<div id="content">
#{doLayout /}
</div>
<!-- common footer here -->
else
Of course used with the if
tag.
#{if user}
Connected user is ${user}
#{/if}
#{else}
Please log in
#{/else}
However, you can also use it with the list
tag and it will be executed if the list is empty.
#{list items:task, as:'task'}
<li>${task}</li>
#{/list}
#{else}
Nothing to do...
#{/else}
elseif
#{if tasks.size() > 1}
Busy tasklist
#{/if}
#{elseif tasks}
One task on the list
#{/elseif}
#{else}
Nothing to do
#{/else}
As for else
, you can use it with the list
tag.
error
Outputs the validation error message, if present, for the field specified by the tag parameter.
#{error 'user.name'/}
You can use the optional field
parameter to use a different field’s error message. This is useful when you want several fields to share a common error message.
#{error 'contact.street', field:'contact.address'/}
#{error 'contact.city', field:'contact.address'/}
#{error 'contact.country', field:'contact.address'/}
errorClass
Outputs the text hasError
if there is a validation error for the field specified by the tag parameter. This is useful for setting a CSS class for input fields with errors:
<input name="name" class="#{errorClass 'name'/}">
which is equivalent to:
<input name="name" class="${errors.forKey('name') ? 'hasError' : ''}">
errors
Iterates over the current validation errors.
<ul>
#{errors}
<li>${error}</li>
#{/errors}
</ul>
The tag defines implicit variables in its body.
error
, the errorerror_index
, the error’s index, starting at 1error_isLast
, true for the last elementerror_isFirst
, true for the first elementerror_parity
, alternates betweenodd
andeven
<table>
<tr><th>#</th><th>Error</th></tr>
#{errors}
<tr class="${error_parity}"><td>${error_index}</td><td>${error}</td></tr>
#{/errors}
</table>
You can also use the optional field parameter, or just the default parameter, to filter only the errors belonging to a certain field.
<ul>
#{errors 'myField'}
There where errors with the field myField<br />
<li>${error}</li>
#{/errors}
</ul>
extends
Makes the template inherit another template.
#{extends 'main.html' /}
field
The field tag is a helper, based on the spirit of the Don’t Repeat Yourself. It works this way:
Instead of writing this:
<p>
<label>&{'user.name'}</label>
<input type="text" id="user_name" name="user.name" value="${user?.name}" class="${errors.forKey('user.name') ? 'has_error' : ''}">
<span class="error">${errors.forKey('user.name')}</span>
</p>
You can just write:
#{field 'user.name'}
<p>
<label>&{field.name}</label>
<input type="text" id="${field.id}" name="${field.name}" value="${field.value}" class="${field.errorClass}">
<span class="error">${field.error}</span>
</p>
#{/field}
So you don’t repeat user.name
again and again.
form
Inserts a form
tag. Play will guess the HTTP method from the route, with POST as the default. If there are both GET and POST routes configured for the URL, the tag will default to using the first route defined in routes.
- Optional
method
either POST or GET. - Optional
id
attribute sets an ID to the form element. - Optional
enctype
attribute sets the form’s data encoding. it defaults to ‘application/x-www-form-urlencoded’.
Charset encoding is always utf-8.
#{form @Client.details(), method:'GET', id:'detailsForm'}
...
#{/form}
Rendered as:
<form action="/client/details" id="detailsForm" method="GET"
accept-charset="utf-8">
...
</form>
You can also specify a target entity as part of the action method:
#{form @Client.details(client.id)}
...
#{/form}
The HTTP parameter name name is detected from what you declared in your action method.
public static void details(String clientId){
// ...
}
Play will create an action URL with clientId:
<form action="/client/details?clientId=3442" method="GET"
accept-charset="utf-8">
...
</form>
The form
tag also automatically includes an authenticity token, for methods other than GET.
#{form @Client.create(), method:'POST', id:'creationForm',
enctype:'multipart/form-data' }
...
#{/form}
Rendered as:
<form action="/client/create" id="creationForm" method="POST"
accept-charset="utf-8" enctype="multipart/form-data">
<input type="hidden" name="authenticityToken"
value="1c6d92fed96200347f06b7c5e1a3a28fa258ef7c">
...
</form>
If your form updates a resource on the server-side, you should use the POST method. If your form is used to filter data and does not update your domain, you can use a GET. Please read about idempotence. POST is not idempotent, whereas GET, PUT and DELETE are.
get
Retrieves a value defined with a set tag. You may use the get/set mechanism to exchange values between templates, layouts and sub-templates.
<head>
<title>#{get 'title' /}</title>
</head>
You can also use the get tag in the following way, which will display “Homepage” if title has not been specified.
<head>
<title>#{get 'title'}Homepage #{/get}</title>
</head>
You can test whether a variable is set using the if
tag:
#{if get('title')}
<h1>#{get 'title' /}</h1>
#{/if}
i18n
Exports localized messages in JavaScript. Localized messages are available from your JavaScript code using the i18n()
function.
Define your translations in the conf/messages
file.
hello_world=Hello, World !
hello_someone=Hello %s !
Include the messages in your template (or layout) page:
#{i18n /}
And retrieve keys from JavaScript:
alert(i18n('hello_world'));
alert(i18n('hello_someone', 'John'));
Optionally, you can restrict the tag to only some messages. The wildcard character is accepted at the end:
#{i18n keys:['title', 'menu.*'] /}
By default, the #{i18n /} tag renders a
<script type="text/javascript">...</script>
tag around the generated JavaScript. You can hide this tag by setting noScriptTag
to true
:
#{i18n keys:['title', 'menu.*'], noScriptTag:true /}
if
Evaluates the given test, and if true, evaluates the tag body.
#{if user.countryCode == 'en' }
Connected user is ${user}
#{/if}
Using composite conditions:
#{if ( request.actionMethod == 'administer' && user.isAdmin() ) }
You are admin, allowed to administer.
#{/if}
ifError
Renders the tag body if there is a validation error for the input field field named by the tag parameter.
#{ifError 'user.name'}
<p>
User name is invalid:
#{error 'user.name' /}
<p>
#{/ifError}
ifErrors
Renders the tag body if any field has a validation error.
#{ifErrors}
<p>Error(s) found!</p>
#{/ifErrors}
ifnot
Cleaner alternative to #{if !condition}
#{ifnot tasks}
No tasks today
#{/ifnot}
include
Includes another template. All of the current template’s variables are directly available in the included template.
<div id="tree">
#{include 'tree.html' /}
</div>
jsAction
The #{jsAction /}
tag returns a JavaScript function which constructs a URL based on a server action and free variables. It does not perform an AJAX request; these have to be done by hand using the returned URL.
- Optional
minimize
attribute sets if script if minimize or not (default : not) - Optional
encodeURI
attribute sets if variables must be encoded (default : not) - Optional
customScript
attribute sets a default script to apply to the variables (default : empty)
Let’s see an example:
GET /users/{id} Users.show
Now you can import this route client side:
Ex1:
<script type="text/javascript">
// Ex 1
var showUserAction = #{jsAction @Users.show(':id') /}
var displayUserDetail = function(userId) {
$('userDetail').load( showUserAction({id: userId}) )
}
// Ex 2
var showUserNameAction = #{jsAction @Users.showName(':name'), encodeURI:false, minimize:true /}
$(document).ready(function() {
$('userDetail').load( showUserNameAction({name: "${user?.name?.urlEncode()}"}) )
});
// Ex 3
var showUserNameActionEncodeURI = #{jsAction @Users.showName(':name'), encodeURI:true, minimize:false /}
var displayUserDetailName = function(userName) {
$('userDetail').load( showUserNameActionEncodeURI({name: userName}) )
}
// Ex 4
var showUserNameActionCustomScript = #{jsAction @Users.showName(':name'), customScript:"encodeURIComponent(val.replace('&', '&'))", minimize:false /}
var displayUserDetail = function(userName) {
$('userDetail').load( showUserNameActionCustomScript({name: userName}) )
}
</script>
jsRoute
The #{jsRoute /}
tag is similar to the #{jsAction /}
tag, it returns an object containing both the function which consctructs the URL based on the server action, and the corresponding HTTP method (GET, POST, etc.).
Example:
PUT /users/{id} Users.update
Then, in a template:
<script type="text/javascript">
var updateUserRoute = #{jsRoute @Users.update(':id') /}
$.ajax({
url: updateUserRoute.url({id: userId}),
type: updateUserRoute.method,
data: 'user.name=Guillaume'
});
</script>
list
Iterates over an object collection.
<ul>
#{list items:products, as:'product'}
<li>${product}</li>
#{/list}
</ul>
The tag defines implicit variables in its body. The variable names are prefixed with the loop variable name.
name_index
, the item’s index, starting at 1name_isLast
, true for the last elementname_isFirst
, true for the first elementname_parity
, alternates betweenodd
andeven
<ul>
#{list items:products, as:'product'}
<span class="${product_parity}">${product_index}. ${product}</span>
${product_isLast ? '' : '-'}
#{/list}
</ul>
The items
parameter is optional and can be replaced by the default arg
argument.
So you can rewrite:
#{list items:users, as:'user'}
<li>${user}</li>
#{/list}
as:
#{list users, as:'user'}
<li>${user}</li>
#{/list}
for loops are easy to create using Groovy range object:
#{list items:0..10, as:'i'}
${i}
#{/list}
#{list items:'a'..'z', as:'letter'}
${letter} ${letter_isLast ? '' : '|' }
#{/list}
The as
parameter is optional as well. It uses _
as default variable name:
#{list users}
<li>${_}</li>
#{/list}
option
Insert an option
tag in the template.
value
- option’s value
#{option user.id} ${user.name} #{/option}
Will output:
<option value="42">jto</option>
script
Inserts a script
tag in the template. By convention, the tag refers to a script in /public/javascripts
src
(required) - script file name, without the leading path/public/javascripts
id
(optional) - anid
attribute value for the generatedscript
tagcharset
(optional) - sets source encoding – defaults to UTF-8
The src
parameter can be replaced by the default arg
argument.
#{script 'jquery-1.4.2.min.js' /}
#{script id:'datepicker' , src:'ui/ui.datepicker.js', charset:'utf-8' /}
render
Renders the template specified by the path in the tag parameter. The path is either absolute, or relative to /app/views
#{render 'Application/other.html'/}
select
Insert a select
tag in the template.
name
(required) - attribute sets a name to the select element.
Any unknown attribute will be considered as an HTML attribute, and rendered "as is"
#{select 'booking.beds', value:2, id:'select1'}
#{option 1}One king-size bed#{/option}
#{option 2}Two double beds#{/option}
#{option 3}Three beds#{/option}
#{/select}
Will output:
<select name="booking.beds" size="1" id="select1" >
<option value="1">One king-size bed</option>
<option value="2" selected="selected">Two double beds</option>
<option value="3">Three beds</option>
</select>
This tag can generate options using items
attribute.
items
(optional) - list of objects, used to createoptions
value
(optional) - selected element initems
(note that multiple selections are not supported)labelProperty
(optional) - for each item, attribute used as option’s labelvalueProperty
(optional) - for each item, attribute used as option’s value.id
is used by default
The labelProperty
and valueProperty
shouldn’t be primitive values. So, for example, use an Integer
or Long
variable instead of an int
or long
.
For example, giving a list of User, each having a name attribute:
#{select 'users', items:users, valueProperty:'id', labelProperty:'name', value:5, class:'test', id:'select2' /}
Will output:
<select name="users" size="1" class="test" id="select2" >
<option value="0" >User-0</option>
<option value="1" >User-1</option>
<option value="2" >User-2</option>
<option value="3" >User-3</option>
<option value="4" >User-4</option>
<option value="5" selected="selected">User-5</option>
</select>
set
Define a value which can be retrieved in the same template or any layout with the get
tag.
#{set title:'Admin' /}
#{set style:'2columns' /}
You can also use variables:
#{set title:'Profile of ' + user.login /}
You can define the value of variables in the body:
#{set 'title'}
Profile of ${user.login}
#{/set}
stylesheet
Inserts a link
tag in the template. By convention, the tag refers to a CSS file in /public/stylesheets
src
(required) - file name, without the leading path/public/stylesheets
id
(optional) - anid
attribute value for the generatedlink
tagmedia
(optional) - amedia
attribute value: screen, print, aural, projection…title
(optional) -title
attribute value (or description)
The src
parameter can be replaced by the default arg
argument.
#{stylesheet 'default.css' /}
#{stylesheet id:'main', media:'print', src:'print.css', title:'Print stylesheet' /}
verbatim
Disables HTML escaping in template output, like the raw() Java extension, but for the whole tag body.
${'&'}
#{verbatim}${'&'}#{/verbatim}
In this example, the first line outputs &
while the second line outputs an ampersand.