Template – Implicit objects
errors
The validation errors raised in the controller
flash
Flash scope
lang
The negotiated language
messages
The map of localised messages
out
The output stream writer
params
Current parameters
play
Main framework class
request
The current HTTP request
session
The session scope
Template – Tag grammar
${ client.name }
Evaluates and outputs a variable
${ client?.name }
Displays client.name only if client not null
@{ Controller.action() }
Calculates URL relative path to action
@{ Controller.action().secure() }
Calculates URL relative HTTPS path to action
@@{ Controller.action() }
Calculates URL absolute path to action
@{'path/to/static_content'}
<img src="@{'/public/images/jpdf.png'}" class="center"/>
&{ message.key }
Message are maintained in conf/messages, supports i18
∗{ this is a comment }∗
What else to say?
%{ out.print("HelloWorld") }%
Groovy scripts for UI logic
#{ my.custom.tag /}
A typical custom tag – page context not shared
Template – Standard Tags
#{extends ʻpage.htmlʼ/}
#{doLayout /}
Master template decorators
#{get 'title'}Used if title not set#{/get}
#{set title:ʻHome Pageʼ}
Shared variables between page and master templates
#{include 'tree.html'/}
Includes fragment – page context is shared
#{script id:'myscript' , src:ʻscript.js', charset:'utf-8' /}
#{stylesheet id:'main', media:'print', src:'print.css' /}
Imports script & styles in the page
#{a @Application.logout() }Disconnect#{/a}
#{form @Client.create() , id:'form' enctype:'multipart/form-
data' } ... #{/form}
Handy tags to create anchors and forms
#{verbatim}${'&'}#{/verbatim}
Disables HTML escaping
#{i18n /}
Exports localized messages in Javascript
#{ifErrors} <p>Error(s) found!</p> #{/ifErrors}
Checks for validation errors
#{ifError 'user.name'} #{error 'user.name' /} #{/ifError}
Checks a given error
#{errors} <li>${error}</li> #{/errors}
Iterates over the current validation errors
#{if cond}...#{/if}#{elseif cond}...#{/elseif}#{else}...#{/else}
#{ifnot cond}...#{/ifnot}
Conditional constructs
#{list items:0..10, as:'i'}${i}#{/list}
#{list items:'a'..'z', as:'l'}${l} ${l_isLast ?'':'|' }#{/list}
#{list users}${_}#{/list}
Loop constructs
#{list items:task, as:'task'}${task}#{/list}
#{else}No tasks on the list#{/else}
Tip: Else can be used along with list
#{cache ʻkeyʼ, for:ʼ15minʼ}...#{/cache}
Caches content for 15 minutes
Template – Custom Tags
@FastTags.Namespace("domain")
public class RecaptchaTag extends FastTags {
public static void _recaptcha(Map, ?> args, Closure body, PrintWriter out, ExecutableTemplate template, int fromLine) { …
/app/view/tags/domain/mytag.tag
Custom tag can be called as {#domain.mytag/}
Template – Groovy extension
${ ['red', 'green', 'blue'].join('/') }
red/green/blue
${ (["red", "green", "blue"] as String[]).add('pink').join(' ') }
red green blue pink
${ (['red', 'green', 'blue'] as String[]).contains('green') }
true
${(['red', 'gr', 'blue'] as String[]).remove('gr').join(' ')}
red blue
${ ['red', 'green', 'blue'].last() }
blue
${ new Date(new Date().getTime() - 1000000).since() }
16 minutes ago
${new Date(1275910970000).format('dd MMMM yyyy
hh:mm:ss')}
07 June 2010 01:42:50
${ 1275910970000.asdate('dd MMMM yyyy hh:mm:ss') }
07 June 2010 01:42:50
${726016L.formatSize()}
709KB
${ 42.formatCurrency('EUR').raw() }
€ 42.00
${ 42.page(10) }
5
journ${ ['cnn', 'c+', 'f2'].pluralize('al', 'aux') }
journaux
${ "lorum ipsum dolor".capAll() }
Lorum Ipsum Dolor
${ "lorum ipsum dolor".camelCase() }
LorumIpsumDolor
${ "lorum ipsum dolor".capFirst() }
Lorum ipsum dolor
${ "lorum ipsum dolor".cut('um') }
lor ips dolor
${ "The <blink>tag</blink> is evil".escape().raw() }
The <blink>tag</blink> is evil
${ "one\ntwo".nl2br() }
one<br/>two
${ '<' } ${ '<'.raw() }
< <
${ " (') (\") ".escapeJavaScript().raw() }
(\') (\")
${ "".yesno('yes', 'no') }
no
${ "not empty".yesno('yes', 'no') }
yes
${"Stéphane Épardaud".noAccents()}
Stephane Epardaud
${ "The Play! frameworkʼs manual".slugify() }
the-play-framework-s-manual
${ "x".pad(4).raw() }
x