Thymeleafテンプレートファイルのinclude/repalaceは再帰可能
引き続きThymeleafテンプレートエンジンについて調べたり使ったりしているうちに気がついたのですが、なんと(?)、th:include
属性やth:replace
属性による外部テンプレート断片の読み込み機能は再帰に対応していることがわかりました。・・・というより、もし対応していないとしたらとっても困ったことになるところでした。
th:include
属性とth:replace
属性はともに、別テンプレート・ファイル内で定義されているテンプレート断片ファイルをその属性が記述されている位置に取り込む機能です。両者のちがいは、その属性が指定されているタグの "子要素のかたちで" 読み込むか、タグを "置き換えるかたちで" 読み込むかです。
そして例えば以下のようにincluding.html
とincluded_recursively.html
の2つのテンプレートを用意することで、ツリー構造のような再帰的な構造を持つオブジェクト・グラフをHTMLレンダリングに使用できるのです。
including.html
:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div> <span th:text="${node.content}"> (item's content here.)</span> <ul> <li th:each="node : ${node.children}"> <div th:replace="included_recursively :: item"> (sub-nodes here)</div> </li> </ul> </div> </body>
このテンプレートはth:replace
属性により、Thymeleafテンプレートエンジンに対して、外部のincluded_recursively
という名前のテンプレートからitem
という断片を取り出してレンダリングに使用するよう指示しています。
included_recursively.html
:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <div th:fragment="item"> <span th:text="${node.content}"> (item's content here.)</span> <ul> <li th:each="node : ${node.children}"> <div th:replace="included_recursively :: item"> (sub-nodes here)</div> </li> </ul> </div> </body>
一方、included_recursively
テンプレートのほうでは、th:fragment
属性でテンプレート断片を定義しています。そして、その断片内で自分自身を参照しています(th:replace="included_recursively :: item"
)。
これは強力です。この機能があることで再帰的なオブジェクト・グラフを容易にHTML化できます。この機能がなければ、最大深度を設けて表現可能性を制限するか、HTMLをプログラムコードで生成するかしなくてはならないでしょう。
もっとも再帰可能ということはつまりテンプレート変数の使用方法を誤るとスタックオーバーフローも発生しうるということですが・・・。