テンプレートエンジン
Play には、HTML、XML、JSON、その他あらゆるテキストベースのドキュメントを動的に生成する効率的なテプレートシステムがあります。テンプレートエンジンは式言語として Groovy を使用します。タグシステムによって、再利用可能な機能を作成することができます。
テンプレートは app/views ディレクトリに保存されます。
テンプレートの構文
テンプレートファイルは、一部に動的に内容を生成するためのプレースホルダを持つテキストファイルです。テンプレートの動的な要素は、 Groovy 言語を使用して書かれます。Groovy の構文は Java のそれにとてもよく似ています。
動的な要素はテンプレートの実行中に解決されます。レンダリング結果は、HTTP レスポンスの一部として送信されます。
Expressions: ${…}
動的な要素を作る最もシンプルな方法は、式を宣言することです。ここで使用する構文は ${…} です。この式の評価結果は、この式部分に挿入されます。
例えば、以下のようにします:
<h1>Client ${client.name}</h1>
client が null でないと確信できない場合には、Groovy のショートカットがあります:
<h1>Client ${client?.name}</h1>
これは client が null でない場合にのみ、client の name を表示します。
タグ: #{tagName /}
タグは、パラメータと共に呼ぶことができるテンプレートの断片です。タグに 1 つのパラメータしかない場合、規約によりそのパラメータは “arg” と呼ばれ、省略することができます。
例えば、このタグは JavaScript ファイルをロードするための SCRIPT タグを挿入します:
#{script 'jquery.js' /}
タグは直接閉じるか、終了タグによって閉じられなければなりません:
#{script 'jquery.js' /}
または、以下のようにします。
#{script 'jquery.js'}#{/script}
例えば、 list タグはどんなコレクションでもくり返すことができます。list タグは 2 つの必須パラメータを受け取ります:
<h1>Client ${client.name}</h1>
<ul>
#{list items:client.accounts, as:'account' }
<li>${account}</li>
#{/list}
</ul>
すべての動的な式は、アプリケーションの XSS セキュリティ問題を回避するために、テンプレートエンジンによってエスケープされます。そのため <h1>Title</h1> を含む titile 変数はエスケープされてしまいます:
${title} --> <h1>Title</h1>
エスケープせずに表示したい場合は、明示的に raw() メソッドをコールする必要があります:
${title.raw()} --> <h1>Title</h1>
素の HTML のかなりの部分を表示したい場合は、 #{verbatim /} タグを使用することができます:
#{verbatim}
${title} --> <h1>Title</h1>
#{/verbatim}
アクション: @{…} または @@{…}
Router を使用することで、指定されたルートに対応する URL を (リバースして) 生成することができます。特別な @{…} 構文を使用して、テンプレートからこれを行うことができます。
例えば、以下のようにします:
<h1>Client ${client.name}</h1>
<p>
<a href="@{Clients.showAccounts(client.id)}">All accounts</a>
</p>
<hr />
<a href="@{Clients.index()}">Back</a>
@@{…} 構文は、(とりわけ email, … に便利な) 絶対 URL を生成する点以外は同じです。
メッセージ: &{…}
アプリケーションを国際化する必要がある場合は、 &{…} 構文を使って国際化されたメッセージを表示することができます:
例えば conf/messages ファイルに次のように指定した場合:
clientName=The client name is %s
このメッセージをテンプレートに表示する使い方はシンプルです:
<h1>&{'clientName', client.name}</h1>
コメント: *{…}*
コメントはテンプレートエンジンによって評価されません。コメントはただのコメントです…
*{**** Display the user name ****}*
<div class="name">
${user.name}
</div>
スクリプト: %{…}%
スクリプトは、より複雑な式のセットです。スクリプトは、いくつかの変数を宣言して、いくつかの命令を定義できます。 {…} 構文を使用してスクリプトを挿入してください。
%{
fullName = client.name.toUpperCase()+' '+client.forname;
}%
<h1>Client ${fullName}</h1>
スクリプトは、 out オブジェクトを使用して、動的な内容を直接出力することができます:
%{
fullName = client.name.toUpperCase()+' '+client.forname;
out.print('<h1>'+fullName+'</h1>');
}%
テンプレート内においてくり返しなどの構造を作成するためにスクリプトを使用することができます:
<h1>Client ${client.name}</h1>
<ul>
%{
for(account in client.accounts) {
}%
<li>${account}</li>
%{
}
}%
</ul>
テンプレートが複雑なことをする場所でないことを覚えておいてください。タグを使えるところではタグを使い、そうでない場合は計算処理をコントローラかモデルオブジェクトに移動してください。
テンプレートの継承
テンプレートは別のテンプレートを引き継ぐこと、すなわち、他のテンプレートの一部として取り込まれることができます。
別のテンプレートを継承するには extends タグを使用します:
#{extends 'main.html' /}
<h1>Some code</h1>
main.html テンプレートは標準のテンプレートですが、内容を取り込むために doLayout タグを使用します:
<h1>Main template</h1>
<div id="content">
#{doLayout /}
</div>
タグの作成
アプリケーションのための特別なタグを容易に作成することができます。タグは、 app/views/tags ディレクトリに格納されるシンプルなテンプレートファイルです。テンプレートのファイル名はタグ名として使用されます。このテンプレートファイル名はタグの名前として使用されます。
hello タグを作成するためには、単に app/views/tags/hello.html ファイルを作成してください。
Hello from tag!
設定は一切必要ありません。このタグを直接使用することができます。
#{hello /}
タグパラメータの取得
タグパラメータは、テンプレートの変数として表現されます。変数名は ‘_’ 文字をパラメータ名の前に付けた状態で構成されます。
例えば、以下のようにします:
Hello ${_name} !
そして、この name パラメータをタグに渡すことができます:
#{hello name:'Bob' /}
タグにパラメータが 1 つしかない場合、暗黙的な名前である arg というデフォルトパラメータ名を使うことができます。
例えば:
Hello ${_arg}!
次のようにして、これを容易に使用することができます:
#{hello 'Bob' /}
タグボディの実行
タグが body をサポートする場合、 doBody タグを使用することでタグコードの任意の位置にボディの内容を取り込むことができます。
例えば、以下のようにします:
Hello #{doBody /}!
そして、タグボディをこの名前として渡すことができます:
#{hello}
Bob
#{/hello}
テンプレートにおける Java オブジェクトの拡張
テンプレートエンジン内において Java オブジェクトを使用すると、新しいメソッドが追加されます。これらのメソッドは、元の Java クラスには存在しておらず、テンプレートエンジンによって動的に追加されます。
例えば、テンプレートにおいて数値を簡単にフォーマットするために、 java.lang.Number に format メソッドが追加されます。
数値をフォーマットするのは非常に簡単です:
<ul>
#{list items:products, as:'product'}
<li>${product.name}. Price: ${product.price.format('## ###,00')} €</li>
#{/list}
</ul>
利用できるメソッドの一覧は API ドキュメント で見つけることができます。
独自拡張の作成
プロジェクトが、特別なフォーマットを必要とする場合、独自の拡張を提供することができます。
必要なのは play.templates.JavaExtensions を拡張する Java クラスを作成することだけです。
例えば、数値にカスタム通貨フォーマットを提供するためには、以下のようにします:
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);
}
}
拡張メソッドは static なメソッドであり、ページに書き戻すために java.lang.String を返すべきです。最初のパラメータは拡張されるオブジェクトを保持します。
このフォーマットは以下のようにして使います:
<em>Price: ${123456.324234.ccyAmount()}</em>
テンプレート拡張クラスは Play によって起動時に自動的に検出されます。それらを利用可能にするために必要なのは、アプリケーションを再起動することだけです。
テンプレートで利用可能な暗黙オブジェクト
renderArgs スコープに追加されたすべてのオブジェクトは、テンプレート変数として直接注入されます。
例えば、コントローラからテンプレートに ‘user’ Bean を注入するためには、以下のようにします:
renderArgs.put("user", user );
アクションからテンプレートをレンダリングするとき、フレームワークは以下の暗黙オブジェクトも追加します:
- session, セッションオブジェクト
- flash, フラッシュスコープ
- request, 現在のリクエスト
- params, HTTP パラメータ
- play, play.Play への参照
- lang, 現在の言語
- messages, メッセージの map
- out, 出力オブジェクト
考察を続けます
Play アプリケーションの最後の層は ドメインオブジェクトモデル です。