テンプレート・エンジンThymeleafのチュートリアルを読む(3)
前回に引き続きテンプレート・エンジンThymeleafのチュートリアルの訳出です。今回はイテレーション(繰り返し処理)について。
原典は"Tutorial: Using Thymeleaf"の第6章です(2014/11/1 取得)。
* * *
6 イテレーション
ホームページをつくるという話からはじまって、プロフィール・ページ、そしてユーザにニュースレターの購読してもらうページの話まで来ました。ところで私たちの製品については? 私たちの売り物が何か、訪問者に知ってもらうためには製品リストをつくらなくてはいけないのでは? 答えは言うまでもなくYes。それではとりかかりましょう。
6.1 イテレーションの基本
/WEB-INF/templates/product/list.htmlの中で私たちの製品を一覧するため、テーブルを用意しましょう。各製品はテーブルの1行(<tr>
要素)を使って表示します。テンプレート・ファイルには、〔訳注:実際にテーブルの行をレンダリングするための〕ひな形──私たちの製品をどのように表示するかを例示する──となる行をつくらなくてはなりません。そしてThymeleafに対して、そのひな形を個別の製品ごとに繰り返し使用するよう指示します。
Thymeleaf標準語ではこの目的のために th:each
を用意しています。
th:eachを使う
製品リスト・ページのために、サービス・レイヤから製品のリストを取得して、テンプレートのコンテキストに追加するコントローラが必要になります:
public void process( HttpServletRequest request, HttpServletResponse response, ServletContext servletContext, TemplateEngine templateEngine) { ProductService productService = new ProductService(); List<Product> allProducts = productService.findAll(); WebContext ctx = new WebContext(request, servletContext, request.getLocale()); ctx.setVariable("prods", allProducts); templateEngine.process("product/list", ctx, response.getWriter()); }
続いて、製品リストのイテレーション〔繰り返し処理〕のため、テンプレート内で th:each
を使用します:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>Good Thymes Virtual Grocery</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <h1>Product list</h1> <table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> </tr> <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr> </table> <p> <a href="../home.html" th:href="@{/}">Return to home</a> </p> </body> </html>
上記コードのなかに登場する prod : ${prods}
という属性値は “${prods}
の評価結果の要素ごとに、prodと呼ばれる変数に設定した上で、このテンプレート断片の処理を繰り返せ”という意味です。ここで登場する概念に名前を付けておきましょう:
Note: イテレーション変数prod
は<tr>
要素(および<td>のような内包要素)の内側においてのみ有効です。
6.2 イテレーション中の状態を保持する
th:each
を使用している時、Thymeleafテンプレート・エンジンはイテレーションの状態を保持するためのメカニズムを提供します:ステータス変数です。
ステータス変数は th:each
属性の中で定義され、次のようなデータを〔プロパティとして〕保持します:
- 現在のイテレーション・インデックス〔添字〕。0始まり。
index
プロパティ。 - 現在のイテレーション・インデックス。1始まり。
count
プロパティ。 - イテレーション対象の変数が保持している要素の総数。
size
プロパティ。 - 各回のイテレーション変数。
current
プロパティ。 - 現在の回が偶数回なのか奇数回なのかを示すフラグ。真偽値の
even
/odd
プロパティ。 - 現在の回が初回であることを示すフラグ。真偽値の
first
プロパティ。 - 現在の回が最終回であることを示すフラグ。真偽値の
last
プロパティ。
先ほどの例のなかでこれらを使ってみましょう:
<table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> </tr> <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr> </table>
ご覧のとおり、ステータス変数(例の中では iterStat
)は、 th:each
属性の中でイテレーション変数あとにカンマで区切って名前を指定することで定義できます。イテレーション変数と同様、ステータス変数もまた th:each
属性を持つタグにより定義されたコード断片の中でのみ有効です。
このテンプレートの処理結果を見てみましょう:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Good Thymes Virtual Grocery</title> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/> <link rel="stylesheet" type="text/css" media="all" href="/gtvg/css/gtvg.css" /> </head> <body> <h1>Product list</h1> <table> <tr> <th colspan="1" rowspan="1">NAME</th> <th colspan="1" rowspan="1">PRICE</th> <th colspan="1" rowspan="1">IN STOCK</th> </tr> <tr> <td colspan="1" rowspan="1">Fresh Sweet Basil</td> <td colspan="1" rowspan="1">4.99</td> <td colspan="1" rowspan="1">yes</td> </tr> <tr class="odd"> <td colspan="1" rowspan="1">Italian Tomato</td> <td colspan="1" rowspan="1">1.25</td> <td colspan="1" rowspan="1">no</td> </tr> <tr> <td colspan="1" rowspan="1">Yellow Bell Pepper</td> <td colspan="1" rowspan="1">2.50</td> <td colspan="1" rowspan="1">yes</td> </tr> <tr class="odd"> <td colspan="1" rowspan="1">Old Cheddar</td> <td colspan="1" rowspan="1">18.75</td> <td colspan="1" rowspan="1">yes</td> </tr> </table> <p> <a href="/gtvg/" shape="rect">Return to home</a> </p> </body> </html>
Note: イテレーション変数のおかげで、上記コードの中のテーブルの奇数行にはodd
CSSクラスが設定されています(行数のカウントは0始まりです)。
<td>
タグのcolspan属性とrowspan属性は、<a>
タグにおけるshape属性と同じく、Thymeleafによって自動的に追加されています。これはXHTML 1.0 Strict標準のDTDに準拠するためのもので、それぞれの属性にはデフォルト値が設定されます(私たちが作成したテンプレートではそれらの値を設定していなかったことを思い出してください)。これらについて心配はご無用です。ページの表示内容には影響がないからです。一例として、HTML5(DTDを持ちません)を使っている場合、これらの属性は決して追加されません。
ステータス変数〔訳注:原文では「イテレーション変数」とあるがこれはおそらく間違い〕を明示的に宣言しなかった場合、イテレーション変数の名称の末尾に Stat
を付けた名称で、自動的に生成されます:
<table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> </tr> <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr> </table>
* * *
原典は"Tutorial: Using Thymeleaf"の第5章です(2014/11/1 取得)。
テンプレート・エンジンThymeleafのチュートリアルを読む(1) - M12i.