Thymeleaf 構文一覧

目次
  • 解説
  • 1. はじめに
  • 2. 基本構文
  • 3. ユーティリティメソッド
進捗を変更する




解説

1. はじめに


このページは、Thymeleafでよく使用される構文・ユーティリティメソッドをまとめたチートシートです。重要度の高い構文は目次下のタグに表示されており、クリックすることで該当の構文にスクロールします。

以下、チートシートの見方です。

サーバー実行前のThymeleaf構文を含むHTMLの例

結果

上のHTMLファイルをサーバー実行した後のHTML

2. 基本構文


${…} (値の取得)

${}」で変数を囲うことで値を取得することが可能です。

<p th:text="${id}"></p>

結果

<p>1</p>

'' + ${…} (値の結合)

+」で値や文字列を結合することが可能です。

<p th:text="'Hello ' + ${name}"></p>

結果

<p>Hello DigSkill</p>

th:with (ローカル変数の定義)

th:with="変数名=値"」 で変数を定義して値を代入することが可能です。ただし、利用可能なのは定義したタグの中だけです。

<div th:with="name='DigSkill'">
	<p th:text="${name}"></p>
</div>

結果

<div>
	<p>DigSkill</p>
</div>

th:utext (非エスケープ)

th:utext」を使用することで、HTMLタグをエスケープせずに表示することが可能です。

<p th:text="'Hello<br>' + ${user.name}"></p>
<p th:utext="'Hello<br>' + ${user.name}"></p>

結果(画面出力)

Hello<br>DigSkill
Hello
DigSkill

${param} (リクエストパラメータの取得)

「/index?id=1」のようなリクエストパラメータを取得したい場合、「param」という特別な変数を使用して「param.id」のように指定して取得することが可能です。

<p th:text="${param.id}"></p>

結果

<p>1</p>

${object.id} (フィールドの取得)

オブジェクトの後に、「.(ピリオド)」続きでフィールド名を指定することでフィールドを取得することが可能です。ただし、getterを定義しておく必要があります。

<!-- 以下の場合 getId() というgetterを定義しておく -->
<p th:text="${user.id}"></p>

結果

<p>1</p>

th:object (フィールドの取得)

th:object="${…}"」のように、オブジェクトを指定したタグの中でのみ「*{…}」の形でフィールドを取得することが可能です。

<div th:object="${user}">
	<p th:text="*{id}"></p><!-- ${user.id} と同じ -->
</div>

結果

<div>
	<p>1</p>
<dib>

+, -, *, /, % (算術演算子)

+」「-」「*」「/」「%」が使用可能です。

<p th:text="3 + 2"></p>
<p th:text="3 - 2"></p>
<p th:text="3 * 2"></p>
<p th:text="3 / 2"></p>
<p th:text="3 % 2"></p>

結果

<p>5</p>
<p>1</p>
<p>6</p>
<p>1.5</p>
<p>1</p>

>, <, >=, <= (比較演算子)

>」「<」「>=」「<=」が使用可能です。 ただし、「>」と「<」は使用すべきではないので、代わりに「gt」と「lt」を使用します。また、以下の文字列エイリアスも使用可能です。
ge(>=)」「le(<=)」

<p th:text="3 gt 2"></p>
<p th:text="3 lt 2"></p>
<p th:text="3 ge 2"></p>
<p th:text="3 le 2"></p>

結果

<p>true</p>
<p>false</p>
<p>true</p>
<p>false</p>

==, != (等価演算子)

==」と「!=」が使用可能です。また、以下の文字列エイリアスも使用可能です。
eq(==)」「neqまたはne(!=)」

<p th:text="3 eq 3"></p>
<p th:text="'DigSkill' ne 'DigSkill'"></p>

結果

<p>true</p>
<p>false</p>

x?y:z (条件式)

三項演算子のように、条件を評価した結果により処理を分けることが可能です。

<p th:text="${user.isAdmin} ? '管理者ユーザー' : '一般ユーザー'"></p>

結果

<!-- user.isAdmin が true の場合 -->
<p>管理者ユーザー</p>

x?:y (デフォルト式)

?:(エルビス演算子)」を使用することで、左辺の式の結果がnull以外の場合にはその値を、 nullの場合には右辺の値を取得します。

<p th:text="${user.name} ?: '名無し'"></p>
<!-- 以下の内容と同じ -->
<p th:text="${user.name != null} ? ${user.name} : '名無し'"></p>

結果

<p>DigSkill</p>

_ (処理なしトークン)

Thymeleaf ではタグ間の文字列より、th:textの値が優先されます。しかし、「_(アンダースコア)」を使用することで「th:text」による処理を無かったことにでき、タグ間の文字列をデフォルト値にように使用することが可能です。

<p th:text="${user.name} ?: _">名無し</p>

結果

<p>名無し</p>

|${…}| (リテラル置換)

文字列や変数を「|(縦棒)」で囲うことで、「+」を使わず変数を埋め込んだ文字列を作成することが可能です。リテラル置換内では、文字列を「’(シングルクォート)」で囲う必要はありません。

<p th:text="|Hello ${user.name}|"></p>

結果

<p>Hello DigSkill</p>

th:if (条件分岐)

th:if="条件"」を使用すると、条件がtrueの場合にのみこのタグと中身を表示することが可能です。また、真偽値のtrue以外にも以下の値がtrueと評価されます。

0以外の数値
false, off, no以外の文字列
真偽値でも、数値でも、文字列でも、nullでもない場合
<!-- user.isAdmin = true の場合 -->
<div th:if="user.isAdmin">
	<p>管理者ユーザー</p>
</div>

結果

<div>
	<p>管理者ユーザー</p>
</div>

th:unless (条件分岐)

th:unless="条件"」を使用すると、条件がfalseの場合にのみこのタグと中身を表示することが可能です。また、真偽値のfalse以外にも以下の値がfalseと評価されます。

数値の 0
文字列の false, off, no
null値
<!-- user.isAdmin = false の場合 -->
<div th:unless="user.isAdmin">
	<p>一般ユーザー</p>
</div>

結果

<p>一般ユーザー</p>

th:switch / th:case (多項分岐)

th:switch」と「th:case」をセットで使用することでJavaのswitch文のように条件ごとに表示を変更することが可能です。どの条件にも一致しない場合に表示されるデフォルトとして、「th:case="*"」が使用可能です。

<div th:switch="${user.authLevel}">
    <p th:case="1">マスターユーザー</p>
    <p th:case="2">管理者ユーザー</p>
    <p th:case="3">一般ユーザー</p>
    <p th:case="*">未ログイン</p>
</div>

結果

<!-- user.authLevel = 1 の場合 -->
<div>
	<p>マスターユーザー</p>
</div>

th:each (ループ)

th:each="変数 : 繰り返し可能なオブジェクト"」を使用することで、オブジェクトから値を一つずつ変数に代入し、ループ処理をすることが可能です。

<div th:each="page : ${pages}">
	<p th:text="${page}"></p>
</div>

結果

<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
	<p>Java</p>
	<p>PHP</p>
	<p>Python</p>
</div>

stat (ステータス変数)

ステータス変数を使用することで「th:each」の中で繰り替えし処理のステータスを取得することが可能です。ステータス変数は「th:each」内で、繰り返し用変数の後にカンマ区切りで名前を指定でき、明示的に指定しない場合は、繰り返し用変数の後ろにStatをつけた変数名で作成されます。ステータス変数は以下のデータを保持しています。

index0から始まる現在のインデックス
count1から始まる現在のインデックス
size全要素数
current現在の要素オブジェクト
even現在の繰り返し処理が偶数かどうか
odd現在の繰り返し処理が奇数かどうか
first現在の繰り返し処理が最初かどうか
last現在の繰り返し処理が最後かどうか
<div th:each="page, stat : ${pages}">
	<p th:text="stat.count"></p>
	<p th:text="page"></p>
</div>

結果

<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
	<p>1</p>
	<p>Java</p>
	<p>2</p>
	<p>PHP</p>
	<p>3</p>
	<p>Python</p>
</div>

__${…}__ (プリプロセッシング)

Thymeleaf ではネストした式を作成する場合、先に中の式を評価する必要があります。その場合「_(アンダースコア)」2つで囲うことで、先に評価することが可能です。

<div th:each="page, stat : ${pages}">
	<p th:text="${pages[__${stat.index}__]}"></p>
</div>

結果

<!-- String[] pages = {"Java", "PHP", "Python"}; の場合 -->
<div>
	<p>Java</p>
	<p>PHP</p>
	<p>Python</p>
</div>

[[…]] (インライン化)

[](角括弧)」2つで囲うことで、HTMLタグ外に直接式を記述することが可能です。また、「[()]」で囲うことでHTMLタグをエスケープせずに出力します。(th:utextと同義)

<div th:with="name='Hello<br>' + ${user.name}">
	<p>[[${name}]]</p>
	<p>[(${name})]</p>
</div>

結果(画面出力)

Hello<br>DigSkill
Hello
DigSkill

/*[[${…}]]*/ (JavaScriptのインライン化)

scriptタグに「th:inline="javascript"」を指定することで、scriptタグ内でもThymeleaf式を使用することが可能です。ただし、HTML単体で表示するとエラーが発生するので、コメント化することによりサーバーで実行された場合とHTML単体で表示された場合で処理を分けることが可能です。

<script th:inline="javascript">
	const name = [[${user.name}]];
</script>

<!-- HTML単体で表示される可能性がある場合 -->
<script th:inline="javascript">
	const name = /*[[${user.name}]]*/ 'HTML単体で表示された場合の値';
</script>

#{…} (メッセージを取得する)

#{...} (メッセージ式)」を使用することで「src > resources」直下に作成した「messages.properties」ファイル内に定義したメッセージを取得することが可能です。

greeding.morning = おはようございます!
<p th:text="#{greeding.morning}"></p>

結果

<p>おはようございます!</p>

@{…} (リンクを作成する)

@{…}(リンクURL式)」を使用することで、動的にURLを作成することが可能です。「/」から始まる相対URLを指定した場合は、自動でURL先頭にコンテキストパスが追加されます。
また、「()(丸括弧)」内で値を指定することで、パス・リクエストパラメーターを動的に定義することも可能で、パスを動的に変更する場合は「{}(波括弧)」で囲います。

<a th:href="@{/home/{action}(id=${user.id}, content='Hello', action=${action})}">送信</a>

結果

<a href="/greeting_app/home/create?id=1&content=Hello">送信</a>

th:block (擬似ブロック)

th:block」要素はth属性実行後に削除されるため、th属性を指定するためだけの余分なタグを作成せずにすみます。

<th:block th:if="${user.isAdmin}">
	<p>管理者</p>
</th:block>

結果

<p>管理者</p>

th:insert (フラグメントの挿入)

th:insert="ファイル名::th:fragmentで指定した値"」を使用することで指定したフラグメントを「th:insert」を指定したタグ直下に挿入することが可能です。

<footer th:fragment="copyright">
	&copy; 2022 Dig Skill
</footer>
<div th:insert="footer::copyright"></div>

結果

<div>
	<footer>&copy; 2022 Dig Skill</footer>
</div>

th:replace (フラグメントで置換)

th:replace="ファイル名::th:fragmentで指定した値"」を使用することで指定したフラグメントで「th:replace」を指定したタグを置き換えることが可能です。

<footer th:fragment="copyright">
	&copy; 2022 Dig Skill
</footer>
<div th:replace="footer::copyright"></div>

結果

<footer>&copy; 2022 Dig Skill</footer>

3. ユーティリティメソッド


${#dates.format(…)} (標準ロケールフォーマットで日付をフォーマット)

<p th:text="${#dates.format(today)}"></p>

結果

<p>2022年1月1日 00:00:00 JST</p>

${#dates.formatISO(…)} (ISO8601フォーマットで日付をフォーマット)

<p th:text="${#dates.formatISO(today)}"></p>

結果

<p>2022-01-01T00:00:00.000+09:00</p>

${#dates.format(…, パターン)} (指定したパターンで日付をフォーマット)

<p th:text="${#dates.format(today, 'YYYY-MM-dd HH:mm')}"></p>

結果

<p>2022-01-01 00:00</p>

${#dates.year(…)} (日付のプロパティを取得)

<p th:text="${#dates.year(today)}"></p>
<p th:text="${#dates.month(today)}"></p>
<p th:text="${#dates.day(today)}"></p>
<p th:text="${#dates.dayOfWeekName(today)}"></p>
<p th:text="${#dates.hour(today)}"></p>
<p th:text="${#dates.minute(today)}"></p>
<p th:text="${#dates.second(today)}"></p>
<p th:text="${#dates.millisecond(today)}"></p>

結果

<!-- 2022/01/31 12:34:56:789 の場合 -->
<p>2022</p><!-- 年 -->
<p>1</p><!-- 月 -->
<p>31</p><!-- 日 -->
<p>月曜日</p><!-- 曜日 -->
<p>12</p><!-- 時 -->
<p>34</p><!-- 分 -->
<p>56</p><!-- 秒 -->
<p>789</p><!-- ミリ秒 -->

${#dates.createNow()} (現在日時のDateオブジェクトを作成)

<p th:text="${#dates.createNow()}"></p>

結果

<p>Mon Jan 31 12:34:56 JST 2022</p>

${#numbers.formatInteger(…, 桁数)} (整数の最小桁数を指定)

<p th:text="${#numbers.formatInteger(num,3)}"></p>

結果

<!-- num = 11 の場合 -->
<p>011</p><!-- 指定した桁数になるよう0埋めされる -->

${#numbers.sequence(x, y)} (xからyまでの整数の配列を作成)

<div th:with="nums = ${#numbers.sequence(1, 3)}">
	<div th:each="num : ${nums}">
		<p th:text="${num}"></p>
	</div>
</div>

結果

<div>
	<div>
		<p>1</p>
		<p>2</p>
		<p>3</p>
	</div>
</div>

${#strings.isEmpty(…)} (文字列が空(もしくはnull)かどうかをチェック)

<div th:with="name=''">
    <p th:text="${#strings.isEmpty(name)}"></p>
</div>

結果

<div>
	<p>true</p>
</div>

${#strings.defaultString(…, 'デフォルト')} (文字列が空もしくはnullの場合デフォルト文字列を返却)

<div th:with="name=''">
	<p th:text="${#strings.defaultString(name, '名無し')}"></p>
</div>

結果

<div>
	<p>名無し</p>
</div>

${#strings.contains(…, '文字列')} (指定した文字列が含まれているかどうかをチェック)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.contains(name, 'Dog')}"></p>
</div>

結果

<div>
	<p>false</p>
</div>

${#strings.startsWith(…, '文字列')} (指定した文字列で始まっているかどうかをチェック)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.startsWith(name, 'Dig')}"></p>
</div>

結果

<div>
	<p>true</p>
</div>

${#strings.endsWith(…, '文字列')} (指定した文字列で終わっているかどうかをチェック)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.endsWith(name, 'Skill')}"></p>
</div>

結果

<div>
	<p>true</p>
</div>

${#strings.indexOf(…, '文字列')} (指定した文字列が最初に出現する位置を取得)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.indexOf(name, 'S')}"></p>
</div>

結果

<div>
	<p>3</p><!-- 0 始まりなので 4文字目 -->
</div>

${#strings.substring(…, x, y)} (指定した位置の文字列を切り出す)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.substring(name, 3, 8)}"></p>
</div>

結果

<div>
	<p>Skill</p>
</div>

${#strings.replace(…, …, …)} (指定した文字列で置き換え)

<div th:with="name='DigSkill'">
	<p th:text="${#strings.replace(name, 'S', ' S')}"></p>
</div>

結果

<div>
	<p>Dig Skill</p>
</div>

${#strings.arrayJoin(…, '')} (配列を指定文字列区切りで結合)

<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#strings.arrayJoin(names, '')}"></p>

結果

<p>オンラインプログラミング学習サービスDigSkill</p>

${#arrays.length(…)} (配列の要素数を取得)

<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#arrays.length(names)}"></p>

結果

<p>5</p>

${#arrays.contains(…, …)} (要素が配列に含まれているかどうかをチェック)

<!-- String[] names = {'オンライン', 'プログラミング', '学習サービス', 'Dig', 'Skill'}; -->
<p th:text="${#arrays.contains(names, 'プログラミング')}"></p>

結果

<p>true</p>

${#aggregates.sum(…)} (配列、コレクションの合計値を取得)

<!-- int[] nums = {1, 2, 3, 4, 5}; -->
<p th:text="${#aggregates.sum(nums)}"></p>

結果

<p>15</p>

${#aggregates.avg(…)} (配列、コレクションの平均値を取得)

<!-- int[] nums = {1, 2, 3, 4, 5}; -->
<p th:text="${#aggregates.avg(nums)}"></p>

結果

<p>3</p>