The template engine
Play has an efficient templating system which allows to dynamically generate HTML, XML, JSON or any text-based formatted document. The template engine uses Groovy as an expression language. A tag system allows you to create reusable functions.
Templates are stored in the app/views directory.
Template syntax
A template file is a text file, some parts of which have placeholders for dynamically generated content. The template’s dynamic elements are written using the Groovy language. Groovy’s syntax is very close to Java’s.
Dynamic elements are resolved during template execution. The rendered result is then sent as part of the HTTP response.
Expressions: ${…}
The simplest way to make a dynamic element is to declare an expression. The syntax used here is${…}. The result of evaluating the expression is inserted in place of the expression.
For example:
<h1>Client ${client.name}</h1>
If you can’t be sure of client being null, there is a Groovy shortcut:
<h1>Client ${client?.name}</h1>
Which will only display the client name if the client is not null.
Template decorators : #{extends /} and #{doLayout /}
Decorators provide a clean solution to share a page layout (or design) across several templates.
Use #{get} and #{set} tags to share variables between the template and the decorator.
Embedding a page in a decorator is the matter of a one liner:
#{extends 'simpledesign.html' /}
#{set title:'A decorated page' /}
This content will be decorated.
The decorator : simpledesign.html
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>#{get 'title' /}</title>
<link rel="stylesheet" type="text/css" href="@{'/public/stylesheets/main.css'}" />
</head>
<body>
<h1>#{get 'title' /}</h1>
#{doLayout /}
<div class="footer">Built with the play! framework</div>
</body>
</html>
Tags: #{tagName /}
A tag is a template fragment that can be called with parameters. If the tag has only one parameter, by convention it is called “arg” and its name can be omitted.
For example, this tag inserts a SCRIPT tag to load a JavaScript file:
#{script 'jquery.js' /}
A tag has to be closed, either directly or by an end tag:
#{script 'jquery.js' /}
or
#{script 'jquery.js'}#{/script}
For example the list tag allows iteration over any collection. It takes two mandatory parameters:
<h1>Client ${client.name}</h1>
<ul>
#{list items:client.accounts, as:'account' }
<li>${account}</li>
#{/list}
</ul>
All dynamic expressions are escaped by the template engine to avoid XSS security issues in your application. So the title variable containing <h1>Title</h1> is now escaped:
${title} --> <h1>Title</h1>
If you really want to display it in an unescaped way, you need to explicitely call the raw() method:
${title.raw()} --> <h1>Title</h1>
Also, if you want to display a large part of raw HTML, you can use the #{verbatim /} tag:
#{verbatim}
${title} --> <h1>Title</h1>
#{/verbatim}
Actions: @{…} or @@{…}
You can use the Router to (reverse) generate a URL corresponding to a specified route. From a template you can use the special @{…} syntax to do that.
For example:
<h1>Client ${client.name}</h1>
<p>
<a href="@{Clients.showAccounts(client.id)}">All accounts</a>
</p>
<hr />
<a href="@{Clients.index()}">Back</a>
The @@{…} syntax does the same but generates an absolute URL (notably useful for e-mail, …).
Messages: &{…}
If your application needs internationalization you can use the &{…} syntax to display an internationalized message:
For example in the files conf/messages we specify:
clientName=The client name is %s
To display this message in a template, simply use:
<h1>&{'clientName', client.name}</h1>
Comment: *{…}*
Comments aren’t evaluated by the template engine. They are just comments…
*{**** Display the user name ****}*
<div class="name">
${user.name}
</div>
Scripts: %{…}%
A script is a more complicated set of expressions. A script can declare some variables and define some statements. Use the {…} syntax to insert a script.
%{
fullName = client.name.toUpperCase()+' '+client.forname;
}%
<h1>Client ${fullName}</h1>
A script can write dynamic content directly using the out object:
%{
fullName = client.name.toUpperCase()+' '+client.forname;
out.print('<h1>'+fullName+'</h1>');
}%
You can use a script to create a structure such as an iteration in your template:
<h1>Client ${client.name}</h1>
<ul>
%{
for(account in client.accounts) {
}%
<li>${account}</li>
%{
}
}%
</ul>
Bear in mind that a template is not a place to do complex things. So, use a tag when you can, or move the computations into the controller or the model object.
Template inheritance
A template can inherit another template, i.e. it can be included as a part of an other template.
To inherit another template, use the extends tag:
#{extends 'main.html' /}
<h1>Some code</h1>
The main.html template is a standard template, but it uses the doLayout tag to include the content:
<h1>Main template</h1>
<div id="content">
#{doLayout /}
</div>
Custom template tags
You can easily create specific tags for your application. A tag is a simple template file, stored in theapp/views/tags directory. The template’s file name is used as the tag name.
To create a hello tag, just create the app/views/tags/hello.html file.
Hello from tag!
No need to configure anything. You can use the tag directly:
#{hello /}
Retrieve tag parameters
Tag parameters are exposed as template variables. The variable names are constructed with the ‘_’ character prepended to the parameter name.
For example:
Hello ${_name} !
And you can pass the name parameter to the tag:
#{hello name:'Bob' /}
If your tag has only one parameter, you can use the fact than the default parameter name is arg and that its name is implicit.
Example:
Hello ${_arg}!
And you can call it easily using:
#{hello 'Bob' /}
Invoke tag body
If your tag supports a body, you can include it at any point in the tag code, using the doBody tag.
For example:
Hello #{doBody /}!
And you can then pass the name as tag body:
#{hello}
Bob
#{/hello}
Format-specific tags
You can have different versions of a tag for different content types and Play will select the appropriate tag. For example, Play will use the app/views/tags/hello.html tag when request.format is html, andapp/views/tags/hello.xml when the format is xml.
Whatever the content type, Play will fall back to the .tag extension if a format-specific tag is not available, e.g. app/views/tags/hello.tag.
Custom Java tags
You can also define custom tags in Java code. Similarly to how JavaExtensions work by extending theplay.templates.JavaExtensions class, to create a FastTag you need to create a method in a class that extends play.templates.FastTags. Each method that you want to execute as a tag must have the following method signature.
public static void _tagName(Map<?, ?> args, Closure body, PrintWriter out,
ExecutableTemplate template, int fromLine)
Note the underscore before the tag name.
To understand how to build an actual tag, let’s look at two of the built-in tags.
For example, the verbatim tag is implemented by a one-line method that simply calls the toString method on the JavaExtensions, and passes in the body of the tag.
public static void _verbatim(Map<?, ?> args, Closure body, PrintWriter out,
ExecutableTemplate template, int fromLine) {
out.println(JavaExtensions.toString(body));
}
The body of the tag would be anything between the open and close tag. So
<verbatim>My verbatim</verbatim>
The body value would be
My verbatim
The second example is the option tag, which is slightly more complex because it relies on a parent tag to function.
public static void _option(Map<?, ?> args, Closure body, PrintWriter out,
ExecutableTemplate template, int fromLine) {
Object value = args.get("arg");
Object selection = TagContext.parent("select").data.get("selected");
boolean selected = selection != null && value != null
&& selection.equals(value);
out.print("<option value=\"" + (value == null ? "" : value) + "\" "
+ (selected ? "selected=\"selected\"" : "")
+ "" + serialize(args, "selected", "value") + ">");
out.println(JavaExtensions.toString(body));
out.print("</option>");
}
This code works by outputting an HTML option tag, and sets the selected value by checking which value is selected from the parent tag. The first three lines set variables for use in the output output. Then, the final three lines output the result of the tag.
There are many more examples in the source code for the built in tags, with varying degrees of complexity. See FastTags.java in github.
Tag namespaces
To ensure that your tags do not conflict between projects, or with the core Play tags, you can set up namespaces, using the class level annotation @FastTags.Namespace.
So, for a hello tag, in a my.tags namespace, you would do the following
@FastTags.Namespace("my.tags")
public class MyFastTag extends FastTags {
public static void _hello (Map<?, ?> args, Closure body, PrintWriter out,
ExecutableTemplate template, int fromLine) {
...
}
}
and then in your templates, you would reference the hello tag as
#{my.tags.hello/}
Java object extensions in templates
When you use your Java object within the template engine, new methods are added to it. These methods don’t exist in the original Java class and are dynamically added by the template engine.
For example, to allow easy number formatting in a template, a format method is added tojava.lang.Number.
It’s then very easy to format a number:
<ul>
#{list items:products, as:'product'}
<li>${product.name}. Price: ${product.price.format('## ###,00')} €</li>
#{/list}
</ul>
The same applies to java.util.Date.
The Java extensions manual page lists the available methods, by type.
Create custom extensions
Your project may have specific formatting needs, in which case you can provide your own extensions.
You only need to create a Java class extending play.templates.JavaExtensions.
For instance, to provide a custom currency formatter for a number:
package ext;
import play.templates.JavaExtensions;
public class CurrencyExtensions extends JavaExtensions {
public static String ccyAmount(Number number, String currencySymbol) {
String format = "'"+currencySymbol + "'#####.##";
return new DecimalFormat(format).format(number);
}
}
Each extension method is a static method and should return a java.lang.String to be written back in the page. The first parameter will hold the enhanced object.
Use your formatter like this:
<em>Price: ${123456.324234.ccyAmount()}</em>
Template extension classes are automatically detected by Play at start-up. You just have to restart your application to make them available.
Implicit objects available in a template
All objects added to the renderArgs scope are directly injected as template variables.
For instance, to inject a ‘user’ bean into the template from a controller:
renderArgs.put("user", user );
When you render a template from an action, the framework also adds implicit objects:
Variable | Description | API documentation | See also |
---|---|---|---|
errors | Validation errors | play.data.validation.Validation.errors() | Validating HTTP data |
flash | Flash scope | play.mvc.Scope.Flash | Controllers - Session & Flash Scope |
lang | The current language | play.i18n.Lang | Setting up I18N - Define languages |
messages | The messages map | play.i18n.Messages | Setting up I18N - Externalize messages |
out | The output stream writer | java.io.PrintWriter | |
params | Current parameters | play.mvc.Scope.Params | Controllers - HTTP parameters |
play | Main framework class | play.Play | |
request | The current HTTP request | play.mvc.Http.Request | |
session | Session scope | play.mvc.Scope.Session | Controllers - Session & Flash Scope |
In addition to the list above the names owner, delegate and it are reserved in Groovy and shouldn’t be used as variable names in templates.
Next: Form data validation
The template engine的更多相关文章
- 如何选择Javascript模板引擎(javascript template engine)?
译者 jjfat 日期:2012-9-17 来源: GBin1.com 随着前端开发的密集度越来越高,Ajax和JSON的使用越来越频繁,大家肯定免不了在前台开发中大量的使用标签,常见到的例子如下: ...
- [PowerShell]template engine
今天讨论的是如何在Powershell里实现一个简单的Template Engine的功能. 假设模板文件的内容如下:template.tt hello $name welcome $company ...
- JFinal Template Engine 使用
官方文档:JFinal Template Engine 文档
- 【Reship】use of tangible T4 template engine
1.first of all 之前在 “使用T4模板生成代码 – 初探” 文章简单的使用了T4模板的生成功能,但对于一个模板生成多个实例文件,如何实现这个方式呢?无意发现一个解决方案 “Multipl ...
- 最近兰州的js风格写个插件和一个template engine
/* *@Product Name: Rational Framework Author: Calos Description: pager !important: pager */ (functio ...
- Js template engine
P http://www.jquery4u.com/javascript/10-javascript-jquery-templates-engines/ http://www.creativebloq ...
- Juicer——a fast template engine
https://blog.csdn.net/yutao_struggle/article/details/79201688 当前最新版本: 0.6.8-stable Juicer 是一个高效.轻量的前 ...
- 500 Lines or Less: A Template Engine(模板引擎)
介绍: 多数项目都是包含很多的逻辑处理,只有少部分的文字文本处理.编程语言非常擅长这类项目.但是有一些项目只包含了少量的逻辑处理,大量的文本数据处理.对于这些任务,我们期望有一个工具能够很好的处理这些 ...
- [Pug] Template Engine -- Jade/ Pug
Looking at the follow code: .wrapper - const upName = name && name.toUpperCase(); h2 | Hello ...
随机推荐
- 快速入门系列--TSQL-01基础概念
作为一名程序员,对于SQL的使用算是基础中的基础,虽然也写了很多年的SQL,但常常还是记不清一些常见的命令,故而通过一篇博文巩固相关的记忆,并把T-SQL本身的一些新特性再进行一次学习. 首先回顾基础 ...
- 利用border属性制作各种图形。
这是一个比较正常的 但如果我们把宽度和高度去掉呢? 好像看不太出来对吧,我们来给边框加上不同颜色. 看出啥了没,分明就是每个边都是一个三角形啊. 那假如我想要一个朝下的三角形是不是我只要把border ...
- 程序是如何执行的(一)a=a+1
本文链接:http://www.orlion.ml/35/ 一.概述 1.计算机中有两个主要的核心部件:CPU和内存,其中CPU负责运算而内存负责存储程序和相关的变量,每一条程序语句和变量都在内存中有 ...
- 在IIS中部署ASP.NET 5应用程序遭遇的问题
用VS2015中创建了一个非常简单的ASP.NET5程序: 在Startup.cs中只输入一行代码: using System; using Microsoft.AspNet.Builder; usi ...
- 碉堡了! 纯 CSS 绘制《辛普森一家》人物头像
这篇文章给大家分享一组纯 CSS 绘制的<辛普森一家>人物头像.<辛普森一家>(The Simpsons)是马特·格勒宁为美国福克斯广播公司创作的一部动画情景喜剧.该剧通过对霍 ...
- Twitter Bootstrap 3.0 正式发布,更好地支持移动端开发
Twitter Bootstrap 3.0 终于正式发布了.这是一个圆滑的,直观的和强大的移动优先的前端框架,用于更快,更容易的 Web 开发.几乎一切都已经被重新设计和重建,更好的支持移动端设备. ...
- 《HelloGitHub月刊》第04期(秋招临近,本期加入了面试相关的项目)
兴趣是最好的老师,而<HelloGitHub> 就是帮你找到兴趣! 因为我比较熟悉python语言,所以月刊中python语言的项目居多,个人能力有限,其他语言涉及甚少,欢迎各路人士加入, ...
- Eclipse JAVA文件注释乱码
将别人的项目或JAVA文件导入到自己的Eclipse中时,常常会出现JAVA文件的中文注释变成乱码的情况,主要原因就是别人的IDE编码格式和自己的Eclipse编码格式不同. 总结网上的建议和自己的体 ...
- java类加载器-系统类加载器
系统类加载器 系统类加载器可能都耳详能熟,但是为了完整点,还是先简单的说说系统的类加载器吧. public class Test { public static void main(String[] ...
- Android序列化之Serializable和Parcelable
PS:还有几天就开学了.先来一发. 学习内容: 1.序列化的目的 2.Android中序列化的两种方式 3.Parcelable与Serializable的性能比较 4.Android中如何使用Par ...