This is Play-Rythm specific feature. To make it consistent with Play convention, calling to an application class instance public property will automatically get translated to the corresponding get/set method:

Properties enhancement is NOT like JavaBean invokation as documented in Velocity Case Subsitituion. It only happen when your model has a public field called “name”, otherwise the above statement will fail.

Unlike Groovy template which all expressions are escaped by default, Rythm template won’t do that due to performance concern. You must explicitly call escape java object extension to escape the variable:

Start from v1.0, PlayRythm escape expressions automatically as html format if the template file name suffix is “.html”. To output an expression by raw data, one can do:

@myVar.raw()

If you have a block of code that you would like to turn of the default escape behavior, you can use

@raw() {
echo @myVar @// this will not be escaped
}

In addition to HTML escape, PlayRythm provides escape to the following format as well:

@ is also used to invoke built-in functions. Built-in function could be treated as special type of tags. From the user’s perspective there is no difference between calling a built-in function and calling a tag (either built-in or custom)

The “tag” in Rythm is kind like “macro” in Velocity and WebMacro, which provides a way to enable template content reuse at runtime. However Rythm tag facility are more powerful than macro in Velocity and FreeMarker. See Tag invocation for more information. In addition, Rythm (start from 1.0 RC5) provides @macro and @exec for parsing time content reuse.

Because Rythm template engine use the same caret @ for both expression evaluation and tag invocation, there might be name conflict between invoking a tag and evaluating an expression. However in most cases this conflict could avoid. Suppose you have a tag file named hello.html, and you have a template defined with hello variable declared:

Tag in Rythm is a powerful tool to reuse your template design. In Velocity and FreeMarker reusing is achieved via a tool named Macro. A Macro is roughly equals to inline tag provided in Rythm. Tag, however is much more powerful than it, and here enumerate some of the Tag advantages over Macro

Tag is a powerful tool to reuse your template definition in Rythm. To invoke a tag, use @ plus tag name and brace

@// call greenscript.js tag using parameters to declare a list of javascript files and output them all
@greenscript.js("app<jqueryui<jquery", all:true)
@// call verbatim tag with a tag body instead of parameters
@verbatim() {
the content within verbatim body will not get parsed by Rythm
@foo.bar()
}

You must append () to tag name even it does not require any parameter. The only exception to this rule is @return, @break and @continue. Because these three are Java reserved words and one cannot use them as variable/method names.

And in another template you want to invoke hello.html. Like groovy template, you can pass an argument to a tag by name:

@hello(title = "Mr.", who = "Green")

or this is also good:

@hello(title: "Mr.", who: "Green")

Unlike groovy template, you are free to pass arguments to tag by position in Rythm template:

@hello("Mr.", "Green)

Controller action invocation is a special kind of tag invocation. However you should NOT pass arguments by name when you invoke a controller action, instead always pass argument by position when you invoke a controller action

Tag invocation decoration feature is also available to an arbitrary template block via the @chain built-int tag

Tag invocation decoration features only process runtime result and thus is NOT available to @include built-in tag because it is evaluated at parsing time and executed at code generating time. For the same reason they are not applicable to Inline tags because inline tags are actually member functions of the underline template class, calling to inline tag are static linked.

The above statement invoke tag myTag using parameter [1, 2, “3”] and cache the result for one hour. Within the next one hour, the tag will not be invoked, instead the cached result will be returned if the parameter passed in are still [1, 2, “3”].

So you see Rythm is smart enough to cache tag invocation against tag name and the parameter passed in. If the tag has body, the body will also be taken into consideration when calculating the cache key.

In some cases where the tag invocation result is not merely a function of the tag, parameter and body, but also some implicit variables, where you might expect different result even you have completely the same signature of tag invocation. Rythm provide way for you to take those additional implicit variable into account when calculating the cache key:

So when platform is iphone, the above case has the same effect as calling @designer.iphone().

Usually when a tag been invoked cannot be found, Rythm will report an error. Sometimes it is expected that certain template/tag does not exists, in which case one can use .ignoreNonExistsTag() extension with invoke keyword:

You can easily create specific tags for your application. Every template can be invoked as a tag. The template’s file path start from template root (in Play context it’s app/rythm) mapped into tag name by striping off the file extension and converting all path separator / into the dot ..

For example suppose you have a template with the following content located at app/rythm/util/hello.html:

Hello from tag!

From the any other template or even the template itself you can invoke the template as a tag:

@util.hello() @// the brace () is a must to call a tag

Retrieve tag parameters

Tag parameters are exposed as template variables which declared using @args tag.

Suppose both request will result in a tag invocation @user.list() in the template code as below:

//@ template code
@args List<User> users
...
@user.list()
...

When you have normal html page request, Rythm will try to look for app/rythm/user/list.html file when doing the tag invocation. If the request is for a json data, Rythm will pickup app/rythm/user/list.json first. If the preferred tag file cannot be found, then Rythm look for tag file for other formats in the following sequence:

So this actually the scope from defining an inline tag to defining a reusable method. This feature allows developer to actually extends a template class and greatly improve the reusability.

The cool part of this feature is it allows developer to define inline tag in the parent (layout) template and used in the descendant templates. Furthermore, the inline tag method is also available to templates which included the template defined it.

Honestly creating Java tag is not so important in Rythm as it is in Groovy because Rythm template is running so fast that it is almost like a handwriting StringBuilder appended java code. However you might still want to do it because the logic in that tag is complicated and it is more easier to code in a Java source code than in a text template source.

PlayRythm provides a bridge to intercept a rythm tag call to FastTags call. So you are free to continue define FastTags as you did for Groovy template. See http://www.playframework.org/documentation/1.2.4/templates#fasttags for more details on how to create FastTags.

Developer cannot use all stuffs in FastTags. The constraints include Closure parameter and TagContext etc.

The above statement will put the content of template foo.bar in place. “foo.bar” is translate into file name following tag invocation convention.

The difference between @include(“foo.bar”) a tag and call the tag via @foo.bar() is the former put the content of the template into the current template inline, while the latter invoke the template specified. It is some how like #include vs. function call in c language. @include is super fast to reuse part of template because it suppress the function invocation at runtime. It’s a inline function call if you speak c++. In other words, @include process happen at template parsing time, while tag invocation happen at template executing time.

If you switch tag invocation to @include and found something has changed even there is no parameter call it might because you have @extended layout template in the tag template. include will NOT be able to include the layout template parts

Because @include are parsed at parsing time therefore it’s not possible to include template dynamically as shown below:

@include("my.common.tag.lib").cache().assign("someVariable").raw() @// THIS WON'T WORK
@my.common.tag.lib().cache().assign("someVariable").raw() @// this works
@// the following also works
@chain().cache().assign("someVariable").raw() {
@include("my.common.tag.lib")
}

A good feature provided with @include is that you can import the inline tag definition from the template been included into the current template:

Suppose you have created a template named app/rythm/util.html with a set of inline tags:

@tag hi (String who) {
Hi @who
}
@tag bye (String who) {
Bye @who
}

Now in your normal template you can import all the inline tags [hi, bye] and call them like a local function:

@include("util")
@hi("rythm")
@bye("rythm")

While @tag provides an alternative to Helper in Razor, the @include provides an alternative to Reusing @helpers across multiple views. See Scott’s blog and search for "reusing @helpers across multiple views"

Like @include, macro provides a way to reuse template content at parsing time, but inside a template file. Suppose you defined a macro called “macro-1”:

@macro("macro-1") {
content inside macro-1
}

Later on in the same template file you can invoke “macro-1” using the following code:

@exec("macro-1")

which produce the following output:

content inside macro-1

At first glance this effect could be achieved using inline tag or even assignment. However they are fundamentally different in that macro executing happen at parsing time while tag invocation and assignment are happened at runtime, which could result in subtle differences of content been rendered. Let’s take a look at the following code:

The result will not be expected. The reason is assignment will evaluate the content at runtime, and when “foo” content is assigned, the content is already produced and later on calling it in @compact and @nocompact block will not make any change. For the same reason the following code works neither:

Macro will be expanded at parsing time, therefore it is very fast at runtime but will generate larger class byte codes, furthermore macro will guaranteed to be executed when invoked with @exec, this is unlike @assign, which is executed for only once when assignment happen.

Before PlayRythm v1.0 you follow the same rule as groovy #extends tag, i.e. you need to pass the full path to extended template file starting from app/rythm folder: @extends(“main.html”)

Since v1.0 you have a clean and simple way to declare extended template, i.e. the way to declare a tag invocation. For example, if you want to extend app/rythm/layout/foo/bar.html, you can declare the extend statement as @extends(“layout.foo.bar”).

In the above example people with sharp eyes can notice that the footer section render in the layout template is different from the sidebar section in that we supplied a default content to the former. So if user did not define the footer section in the sub template, the default content will be output instead. This is an new feature available in v1.0

Unlike Play’s Groovy template that all objects added to the renderArgs scope are directly injected as template variables, you must declare them (and might need to import their class packages) to use them freely in your template. PlayRythm plugin automatically declare and set the following implicit objects so that you don’t need to do these job before using them:

So as you can see most of these implicit variables are the same as those defined in Groovy templates. The only exception is Groovy’s implicit variable play has been renamed to _play. The reason for this is I want to allow user to use full qualified classes in play.* package.

If you have put something into your RenderArgs, and you didn’t declare it using @args statement, you are still able to access it via getRenderArg() method. But please be noted that all stuff you get via getRenderArg() call are Object type, and you need to explicitly cast them before accessing properties and methods of them: