Skip to content

Latest commit

 

History

History
867 lines (561 loc) · 25.5 KB

reference.textile

File metadata and controls

867 lines (561 loc) · 25.5 KB

PlayRythm Reference

Play specific tag. Lookup message string.

@msg("validation.required")

The above has the same effect of the following groovy template code:

&('validation.required')

You can also pass parameters:

@msg("some.message", "param1")

You can pass variable as message (Start from v1.0.0-20120718):

@{String message = "validation.required"}
@msg(message)

Play specific tag. Reverse lookup URL.

@url(Application.index)

The above code is equal to the following groovy template code:

@{Applicaiton.index}

You can also reverse lookup static url

@url(/public/javascripts/myscript.js)

Play specific tag. Absolute reverse lookup URL.

@fullUrl(Applicaiton.index)

The above code is equal to the following groovy template code:

@@{Application.index}

Assign the enclosed block into a variable.

@assign("roleSelector") {
<select>
@for(Role role: Role.findAll()){
<option value="@role.getId()">role.toString()</option>
}
</select>
}
...
<label>select role</label>
@roleSelector.raw()

The variable name specified in @assign must be unique across the context where @assign is put in. Otherwise you will expect a compilation exception

assign to a final variable

To assign to a final variable pass the second parameter true:

@assign("roleSelector", true) {
<select>
@for(Role role: Role.findAll()){
<option value="@role.getId()">role.toString()</option>
}
</select>
}

The benefit of final variable is that you can use it directly inside @for loop.

The args tag declare variables used in the template.

@args String var1, int var2, ...

or declare render arguments in multiple lines (start from 1.0.0-RC7):

@args {
    String var1, int var2
    boolean var3
    ...
}

args is one of few tags that are not invoked in tag(...) style. At the moment please use ";" to terminate @args statement. This limitation will be removed in the future, and line-break could be an natural way to terminate the statement

You can have any arbitrary number of args statement in any where of your template, all variables declared will be effective in your template.

PlayRythm specific tag. This is a clone of the authenticityToken tag in Play’s groovy template.

@authenticityToken()

Rendered as:

<input type="hidden" name="authenticityToken"
    value="1c6d92fed96200347f06b7c5e1a3a28fa258ef7c">

PlayRythm specific tag. Use authenticityTokenValue when you want to put the authenticity token value inside a javascript code in your view:

$.post("@url(User.save())",
    {authenticityToken: '@authenticityTokenValue()', ...},
    function(data){...});

Rendered as:

$.post("/user/save",
    {authenticityToken: "1c6d92fed96200347f06b7c5e1a3a28fa258ef7c", ...},
    function(data){...});

Break @for loop

@for(User user: users) {
	@if(theUserId.equals(user.getId())) {
		@break
	}
}

Caches the tag body or use cached tag body

@cache("5min") {
    <p>This content will be cached for 5 minutes</p>
    including calling to any tags like:
    @myTag()
}

Parameters:

  • empty parameter: the enclosed content get cached for duration defined in “rythm.cache.defaultTTL” seconds.By default it’s one hour
  • first parameter: optional. specify the cache duration. Examples:
    • “5min”, five minutes
    • “1h”: one hour
    • “10s”: ten seconds
    • “360d”: three hundred and sixty days
    • “forever”: a fairly large time that could be considered forever in the current computing context
    • 60 * 60: one hour
  • rest parameters: optional. specify the variables used in the cache key generation. By default cache key is calculated literally using the enclosed content. However if rest parameters presented the cached key will be calculated using the parameters as well. For example
@cache(null, new Random().nextInt()) {
    <p>[@(new Date().getTime())]this content will literally looks like not cached at all because the cache key changes every time</p>
}

Be cautious when you use @cache() with template blocks contains dynamic content or nested dynamic content via @include() or tag invocation. Cache key is calculated literally based on the content at parsing time, while dynamic content might changes at runtime. The rule of thumb is: if content or nested content via tag invocation or include varies dynamically, do not cache it, or you cache it and pass all variables used across the content and nested content via tag invocation and include directive

The cache decoration to tag invocation is safer than the @cache() directive, because “cache decoration” will check parameter value at runtime when generating cache key:

@myTag(someVariable).cache("1h") // safer cache, cache key will vary if someVariable value changes
@cache("1h"){ // even someVariable value changed, the cache key will be the same so the output will remain unchanged
    @myTag(someVariable)
}

h3. cacheOnProd

Same as “cache”, but cache happens only when play.Play.mode is “prod”.

cacheOnProd is no longer available in v1.0. Use cache instead. However you can configure rythm not to cache in dev mode by using @rythm.cache.prodOnly setting.
By default rythm.cache.prodOnly is set to true so cache is not enabled at dev mode

Chain the following decoration functions together:

  1. cache
  2. escape
  3. raw
  4. assign

In the example of assign, you found that it always needs to call raw() when you want to use the variable get assigned, by using chain you can do it at one time:

@chain.raw().assign("roleSelector") {
<select>
@for(Role role: Role.findAll()){
<option value="@role.getId()">role.toString()</option>
}
</select>
}
...
<label>select role</label>
@roleSelector @// no longer need raw() extension any more

And you even add cache() into the chain:

@chain.raw().assign("roleSelector").cache() {
...
}

The order of the chained function doesn’t matter as they are orthogonal concerns.

Mark a block of template to be output in compact mode without regarding to the global compact setting.

@compact() {
   All content here will be output
   in compact mode.
}

The above code will output the following content:

All content here will be output in compact mode

See also nocompact.

Continue current loop:

@for (User user: users) {
    @if (user.isAdmin()) {
        @continue
    }
    ...
}

AKA @tag, define an inline tag (helper in Razor, macro in velocity and freemarker) which can be invoked from within the same template, the parent template or children templates

@def sayHi(String who) {
    Hi @who
}

To use the tag defined just follow the common way:

@sayHi("Play!framework")

or pass argument by name:

@sayHi(who: "Play!framework")

Inline tag must be defined before the invocation code. Otherwise you might get compilation error.

Define return type of inline tag:

@def boolean isMobile() {
    @{
        UserAgent ua = getRenderArg("userAgent");
        return ua.isMobile();
    }
}

And later on it can be used as:

@if (isMobile()) {
   @mobileTag()
} else {
   @pcTag()
}

See “defining inline tag” in the user guide

Used with template inheritance, this tag inserts the evaluated sub-template’s contents.

<!-- common header here -->
<div id="content">
    @doLayout()
</div>
<!-- common footer here -->

doLayout tag is an alias of render tag

An easier and clean way to @doLayout() is @render()

See also template inheritance

An alias of renderBody

PlayRythm specific tag. Outputs the validation error message, if present, for the field specified by the tag parameter.

@error("user.name")

You can use the optional 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", "contact.address")
@error("contact.city", "contact.address")
@error("contact.country", "contact.address")

PlayRythm specific tag. 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="@(play.data.validation.Validation.hasError("name") ? "hasError" : '')">

Alias of errors. See below.

Corresponding to Groovy template’s errors. Iterates over the current validation errors.

<ul>
@errors() {
    <li>@error</li>
}

The @error tag defines implicit variables in its body.

  • error, the error
  • error_index, the error’s index, starting at 1
  • error_isLast, true for the last element
  • error_isFirst, true for the first element
  • error_parity, alternates between odd and even
<table>
<tr><th>#</th><th>Error</th></tr>
@errors() {
    <tr class="@error_parity"><td>@error_index</td><td>@error</td></tr>
}
</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>
}
</ul>

Mark a block of template code default escape scheme:

@escape("JS"){
    alert("Hello Rythm");
}

The above code set the default escape to JavaScript. The parameter passed to @escape() could be one of the following:

  1. RAW – do not escape. Same effect with @raw()
  2. CSV – escape as csv format
  3. HTML – escape as html format
  4. JS | JavaScript – escape as JavaScript format
  5. JAVA – escape as Java format
  6. XML – escape as XML format

Note

  • the parameter is case insensitive.
  • if no parameter is passed, then it default to HTML
  • you pass the parameter within quotation mark or not

Execute an macro. AKA exec.

@exec("macro1")

See also Define and execute Macro

Expand an macro. AKA exec.

@expand("macro1")

See also Define and execute Macro

Makes the template inherit another template.

@extends(main)

or

@extends("main")

You can pass parameter to extended template if the there are arguments declared.

Suppose you have a parent template defined as:

@args String style;
<div class="panel @style">
    @doLayout()
</div>

And in your extending template, you pass the argument style as:

@extends(panel, style: "span4")

or pass by position:

@extends(panel, "span4")

You can use debug tag to output debug message to your log file or screen:

@debug("this is a debug message for %s", myvar)

Use for to iterate a collection of objects. The syntax is the same as for loop in Java language:

<ul>
@for (Product product: products) {
    <li>@product</li>
} else {
    <div class="alert">No product found</div>
}
</ul>

The else branch syntax is an new feature starting from v1.0.0-20121126 version.

The @for tag defines implicit variables in it’s body. The variable names are prefixed with loop variable name:

  • name_index, the item’s index, start with 1
  • name_isFirst, true for the first element
  • name_isLast, true for the last element
  • name_parity, alternates between odd and even
  • name_isOdd, true if the current element is odd in sequence
  • name_size, the size of the collection
  • name_sep, “,” if the current loop is not at the last item
  • name__sep, loop variable + “,” if the current loop is not at the last item
  • name_utils, the loop utils object
  • name__utils, loop variable + the loop utils object
<ul>
@for (Product product: products) {
    <li class="@product_parity">@product_index. @product</li>
    @product_sep
}
</ul>

If you need a special item separator other than the default xx_sep, you can use xx_utils object:

@for(String s: strList) {
    @s_utils.sep(",")
    @s_utils.preSep(",")
    @s_utils.postSep(",")
}

in the above example, @s_utils.sep(",") is the same as @s_sep and @s_utils.postSep(","), which output a comma if the current loop is NOT at the last item. @s_utils.preSep(",") output a comma if the current loop is not at the first item. This feature is very helpful when you want to print a list of items separated by a certain separator.

If you refer to a local variable inside the loop, you need to make sure they are declared as final:

@{
 String foo = "foo";
 final String bar = foo;
}
@for(MyModel model: myModels) {
    <p>@bar</p> @// this is okay
    <p>@foo</p> @// this line will cause compilation error
    ...
}

You can also use the second form of @for tag:

@for(int i = 0; i < 6; ++i) {
    <li>the current index is @i</li>
}

You don’t have access to loop variables if you use the second @for loop form. Neither can you use else branch along with this second for loop style

Start from v1.0-b4, play-rythm support loop variable type inference. For example:

@args List<User> users
...
@for(user: users) {
    ...
}

In the above case, as you have declared users as List<User> type, you don’t need to declare the type of for loop variable user, Rythm will automatically give type User to it. Type inference also support type inference for Map iterables:

@args Map<String, Integer> myMap
...
@for(key: myMap.keySet()) {...} @// key type is String
@for(val: myMap.values()) {...} @// val type is Integer

Limitation of type inference:

  • The iterable must be declared with @args statement
  • The iterable cannot be an expression, e.g. @for(v: foo.bar()){...}

In the above case when Rythm cannot identify the loop variable type, java.lang.Object will be used as the type of the loop variable

Since v1.0-b4 Play-rythm support new loop styles:

The class Java style:
@for(s : list) {...}
JavaScript style:
@for(s in list) {...}
Scala style:
@for(s <- list) {...}

Since v1.0-b4 Play-rythm support new loop iterable expressions include String separator and Number range:

String separators
@for("a, b, c"){@__sep} @// output: a,b,c
@for("a : b:c"){@__sep} @// output: a,b,c
@for("a; b;c"){@__sep} @// output: a,b,c
@for("a - b - c"){@__sep} @// output: a,b,c
@for("a_b_c"){@__sep} @// output: a,b,c

Separator priority: ; > , > : > _ > -. E.g. “foo;bar,c:d” are separated into two groups: “foo” and “bar,c:d”

Number ranges
@for (1 .. 5) {@_} @// output: 1,2,3,4
@for ([1 .. 5]) {@_} @// output: 1,2,3,4,5

Since v1.0-b4 Play-rythm support new loop separators:

@for("a:b:c"){@__sep} @// new style output a,b,c
@for("a:b:c"){@(_)@_sep} @// old style output a,b,c
@for(s in "a:b:c"){@s__sep} @// new style output a,b,c
@for(s in "a:b:c"){@(s)@s_sep} @// old style output a,b,c
@for("a:b:c"){@__utils.sep("|")} @// new style output a|b|c
@for("a:b:c"){@(_)@_utils.sep("|")} @// old style output a|b|c

Retrieves 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 provide a default value in the following way, which will display “Homepage”, if title has not been specified:

<head>
    <title>@get("title": "Homepage")</title>
</head>

Evaluates a given test, and if true, evaluate the tag body. The syntax is the same as if clause in Java language

@if ("en".equals(user.countryCode)) {
    Connect user is @user
}

You can also use else clause:

@if (null != user) {
    Connected user is @user
} else {
    Please log in
}

or else if clause

@if (tasks.size() > 1) {
    Busy tasklist
} else if (tasks.size() > 0) {
    One task in the list
} else {
    Nothing to do
}

Import package or class.

@import java.awt.*, java.io.*,...

or declare import statements in multiple lines (start from 1.0.0-RC7):

@import {
    java.awt.*, java.io.*
    static java.lang.Math.*
    ...
}

Do an inline include a template into the current template:

@include("common.utils")

See Include other templates section for details

Enable dynamic tag invocation:

@invoke("designer." + platform).ignoreNonExistsTag()

See Dynamic tag invocation section for details4

@jsAction() is a play specific tag that 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.

Let’s see an example:

GET     /users/{id}        Users.show

Now you can import this route client side:

<script type="text/javascript">
    @assign("showUserUrl"){@url(Users.show(":id"))}
    var showUserAction = @jsAction(showUserUrl)
    var displayUserDetail = function(userId) {
        $('userDetail').load( showUserAction({id: userId}) )
    }
</script>

Note at the moment @jsAction() tag in PlayRythm is no as convenient to use as the groovy #{jsAction /} tag that you must use a special @assign statement to get the url reverse lookup result before passing it to the @jsAction() tag:

@assign("showUserUrl"){@url(Users.show(":id"))}
var showUserAction = @jsAction(showUserUrl)

It’s desired the syntax could be simplified as:

var showUserAction = @jsAction(Users.show(":id")) @// note this has NOT been implemented yet!

Define a template macro.

@macro() {
    macro content
}

See also @exec and Define and execute Macro

Mark a block of template to be output NOT in compact mode without regarding to the global compact setting.

@nocompact() {
All content here will be output
in nocompact mode.
}

The above code will output the following content:

All content here will be output
in compact mode

See also compact.

AKA doBody, renderBody is an alias of doLayout. is used to render the tag body.

@renderBody()

If tag body is supplied along with callback extension, then you can pass parameters into renderBody call:

@renderBody(user.role)

or by name:

@renderBody(role: user.role)

AKA renderSection and doLayout, used with template inheritance, this tag inserts the evaluated sub-template’s contents defined with section tag

<div id="sidebar">
    @render("sidebar")
</div>

When no section name specified this tag output the layout content:

@render() @// also @doLayout(), same effect as groovy's #{doLayout/}

Start from v1.0.0 Rythm support define default content for section:

<div id="footer">
    @renderSection("footer") {
        @// here we define default content for footer section
        @// if sub template failed to supply this section then
        @// the default content will be output instead
        <p>Site footer - &copy; Santa Clause</p>
    }
</div>

Abort the template execution and return to caller:

@if(!user.isAdmin()) {
	@return
}
<p class="admin-panel">...

Define a block of template to be output in parent template’s named section.

@section("sidebar") {
    <ul>
        <li><a href="#">Link one</li>
        <li><a href="#">Link two</li>
    </ul>
}

Define a value which can be retrieved in the same template or any layout with the get tag.

@set(title: "Admin")
@set(style: "span6")

You can use any expression in set tag

@set(title:"Profile of " + user.login)

Unlike set tag in Groovy template engine, Rythm set tag does not accept tag body. You can use section tag to achieve the same result.

Analog of the spaceless tag from Django. Removes whitespace (\s) characters between HTML tags, including tabs and newlines.

Template:

@spaceless() {
  <ul>
    <li>First item</li>
    <li>Second   item</li>
  </ul>
}

Output:

<ul><li>First item</li><li>Second   item</li></ul>

Alias of @def()

@tag is not used to invoke a tag. Check the user guide to see how to invoke a tag.

Call the current template itself as a tag

@args int max, int i, int j
@i @if (j < max) {
    @{
        int t = i;
        i = j;
        j = i + t;
    }
    , @this(max, i, j) @// recursively call to this template
} else {
    <hr/>
 
    <h3>Fibonacci tag template source</h3>
    <pre>
        @(getTemplateClass(false).getTemplateSource())
    </pre>
 
    <h3>Fibonacci tag java source</h3>
    <pre>
        @(getTemplateClass(false).javaSource)
    </pre>
}

Mark a block of template code that by default output raw data for expression:

@{
    String title = "<h1>title</h1>";
    String body = "<p>some news</p";
}
@raw() {
    @title
    @body
}

The above code has the same effect as below

@{
    String title = "<h1>title</h1>";
    String body = "<p>some news</p>";
}
@title.raw()
@body.raw()

Output timestamp in place

now is @ts() @// produce somethign like "now is 134325875435"

Define a block of code that not to be parsed by Rythm.

@verbatim() {
    OK, anything inside this block is not parsed: @someTag, @someExpression, etc
}

Mark the current template as a simple template. A simple template is slightly faster than normal template and has the following constraint:

PlayRythm Configuration

PlayRythm provides all default configuration settings that cater for most common use cases.

configuration description default value
rythm.mode set rythm template engine to run in dev or prod mode the value of play.mode
rythm.compactOutput remove redundant space and line breaks true in prod mode and false in dev mode
rythm.enableJavaExtensions enable Java extension parsing true
  1. Integrate PlayRythm into your Play project
  2. Rythm Template User guide