4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Thymeleafの使い方一例

Last updated at Posted at 2023-10-16

Thymeleaf

Thymeleafについて、分からないことが多すぎたため公式ページを確認したが、それでも分からない事が多いので、他の解説しているページ等を参考にまとめたページ。自分が使用することになった内容に重点を置いて書いてます。基本は次の公式ページを参考にしていますが、公式以外を参考にした部分はリンクを張っています。

公式ではないですが、次のチートシートがとても分かりやすく纏められていました。

スタンダード式構文

  • 単純式:
    • 変数式: ${...}
    • 選択変数式: *{...}
    • メッセージ式: #{...}
    • リンクURL式: @{...}
  • リテラル
    • テキストリテラル: 'one text', 'Another one!',…
    • 数値リテラル: 0, 34, 3.0, 12.3,…
    • 真偽値リテラル: true, false
    • Nullリテラル: null
    • リテラルトークン: one, sometext, main,…
  • テキスト演算子:
    • 文字列結合: +
    • リテラル置換: |The name is ${name}|
  • 算術演算子:
    • バイナリ演算子: +, -, *, /, %
    • マイナス符号 (単項演算子): -
  • 論理演算子:
    • 二項演算子: and, or
    • 論理否定演算子 (単項演算子): !, not
  • 比較と等価:
    • 比較演算子: >, <, >=, <= (gt, lt, ge, le)
    • 等価演算子: ==, != (eq, ne)
  • 条件演算子:
    • If-then: (if) ? (then)
    • If-then-else: (if) ? (then) : (else)
    • Default: (value) ?: (defaultvalue)

単純式

変数式: ${...}

  • リクエストパラメータから取得
    リクエストパラメータ(postまたはgetで送られてくるデータ)にname=Tanakaがある場合
    ${param.name[0]}で取得できる。
    リクエストパラメータは同一名称で複数送れるため、配列で保存される。

  • リクエストスコープから取得
    リクエストスコープにname=Tanakaが保存されている場合
    ${name}Tanakaが取得できる。

  • 式のユーティリティオブジェクト
    #ユーティリティオブジェクトで複数のオブジェクトが用意されており、変数式の中に書くことで使える。詳細はThymeleafの公式ページに載っているので、ここではどんなものかイメージ出来るように数個記載する。

    • #stringsユーティリティメソッド一例
      ${#strings.toUpperCase(name)} これで変数nameの値を大文字にする
      nameを文字列として扱う場合は、'name'のようにテキストリテラルとして書く

    • #arraysユーティリティメソッド一例
      ${#lists.isEmpty(list)}これでlistが空かどうかチェックできる

    • #idsユーティリティメソッド一例
      下記のサイトに分かりやすく書かれていたが、調べる前は読んでも理解できなかったので、忘れないように解説を残す。サイトに書かれていたコードとリンクは、解説後に記載する。

  1. ${#numbers.sequence(1,3)これは#numbersユーティリティを使ったもの。{#numbers.sequence(from,to)}でfromからtoまでの整数の配列が作成される。
  2. th:each="seq : ${#numbers.sequence(1,3)}"では作成された配列の値が変数seqに代入され、th:eachを書いたタグ内で繰り返し処理される。
  3. th:id="${#ids.seq('id_hobby_')}"これは#ids.seq('someId')ユーティリティで、id属性値にカウンターの値を加える動作になる。通常th:id属性に使用される。この例ではid_hobby_1id_hobby_2といったようなカウンターの値を加えた動作になる。
  4. th:for="${#ids.prev('id_hobby_')}"#ids.prev('someId')ユーティリティで、通常は<label>タグ内th:for属性に使用される。#ids.seq('someId') 関数で生成されたidをラベルから参照できるようになる。例では直前に書かれたth:id="${#ids.seq('id_hobby_')}"で生成されたidがid_hobby_1の時、th:for="${#ids.prev('id_hobby_')}"も同様の値id_hobby_1になる。後ろにあるidを参照するときはids.next('someId')ユーティリティを使用する。
template
<form>
  <th:block th:each="seq : ${#numbers.sequence(1,3)}">
  <input type="text" name="hobby" th:id="${#ids.seq('id_hobby_')}" value="" />
  <label th:text="|hobby_${seq}|" th:for="${#ids.prev('id_hobby_')}">field</label>
  </th:block>
</form>
render
<form>
  <input type="text" name="hobby" value="" id="id_hobby_1">
  <label for="id_hobby_1">hobby_1</label>
  <input type="text" name="hobby" value="" id="id_hobby_2">
  <label for="id_hobby_2">hobby_2</label>
  <input type="text" name="hobby" value="" id="id_hobby_3">
  <label for="id_hobby_3">hobby_3</label>
</form>

#ids.prev又は#ids.nextメソッドで参照するidは通常#ids.seq('someId') 関数で作成されるidを使用する。#ids.seq('someId') 関数の前で指定するときは#ids.prev、後で使用するときは#ids.nextを使う。
また、inputの部品にth:field属性を付与した場合は内部的に#ids.seqメソッドと同等の処理を実行してidが生成される。このため、タグ内にth:field属性を付与した場合は#ids.seqメソッドを使用しなくて良い。
https://macchinetta.github.io/server-guideline-thymeleaf/current/ja/ArchitectureInDetail/WebApplicationDetail/Validation.html#validation-ids-prev-method

上記のノートではth:field属性を付与すると、内部的に#ids.seq<input>タグ部品textth:field属性を指定したtemplateコードは、nameidvalue属性を明記したrenderコードと同様の内容になる。

template
<input type="text" th:field="*{datePlanted}" />
render
<input type="text" id="datePlanted" name="datePlanted" th:value="*{datePlanted}" />

https://www.thymeleaf.org/doc/tutorials/3.1/thymeleafspring.html

選択変数式: *{...}

変数式${...}とほとんど同じだがth:objectで指定したオブジェクトから値を探す。
指定したオブジェクトに値がない場合、${...}と同じ意味になる。

変数式${…}の中で選択変数式を使う

${*{…}}はエラーとなり使用できない。
#objectを変数式内で使用するとth:objectで設定したオブジェクトを指せる。

<div th:object="${hogehoge}">
  <p>FirstName: <span th:text="${#object.firstName}"></span>.</p>
</div>

メッセージ式: #{...}

別のファイル(通常は.propertiesファイル)に書かれたメッセージと紐づけが出来る。
xxx.propertiesファイルにuser.name=Tanakaが保存されていると
#{user.name}Tanakaが取得できる。

リンクURL式: @{...}

<a th:href=@{...}>のように、<a>タグとth:href属性とセットで使用する。
次コードのように、URLパラメータとして使うことも可能。

<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>

<!-- Will produce '/gtvg/order/details?orderId=4' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id + 1})}">view</a>

ここでは、detailsの後にURLパラメータを追加している。?orderID=3のように変わる。
2つ目の式のように、変数式の中に算術演算子を使うことも可能。

href属性とth:href属性を併記する理由、動作は次のサイトが参考になった。

href属性は、サーバーを通さずに直接ブラウザでHTMLを開いたときに利用されます。そして、サーバー上で実行したときには、href属性の値はth:href属性の値で上書きされます。なぜ、上書きされて消えてしまうhref属性を書くのかというと、直接ブラウザでHTMLを開いてもCSSが適用されるようにするためです。
こうすると、テンプレートをそのままブラウザで開いて、お客様に見せて打ち合わせなどができます。

<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

上記のコードはURL内の{orderId}(orderId=${o.id})がリンクしている。
1つ前のコードでは、(orderId=${o.id})?orderID=3に変わっていたが、このコードでは{orderId}${o.id}の結果である3が代入されている。
記述が似ているが結果は違うので注意が必要だと感じた。

テキスト演算子

リテラル置換

変数式を使った文字列を作成するとき+を使わず簡単に書くことができる。
| |内に書いた文字はそのまま文字として、${}*{}のような変数式は結果が文字として表示される。

<div th:object="${hogehoge}">
  <span th:text="|The name is ${hogehoge.name}|"></span>
  <span th:text="|The name is *{name}|"></span>
</div>

その他の使い方

Bean値を使用

@の後にBean名を書くと、そのBeanを使うことができる。

環境変数を取得

${@environment.getProperty('property.key')}
propertyやymlファイルの値を取得できる。
テキスト演算子の文字列結合と併用しても、property.keyを囲っている''は書き換え不要。
例えば文字に環境変数を結合したいとき下記のように書ける。
"'hoge' + 'hogehoge' + ${@environment.getProperty('property.key')}"

属性に値を設定する

任意の属性に値を設定するにはth:attr属性を使う必要があるが、特定の属性にはth:*属性がたくさん用意されており、通常はth:*属性で対応できる。公式には数個の使用例が記載されている。

<input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">
<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>

参考だが、1行目をth:attr属性で書くとこのようになる。(普通は上記のth:valueを使う)

<input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>

th:if、th:unless属性

th:ifの結果がtrueの場合、th:ifタグ内が実行され、falseの場合は実行されない。
次の公式のコードを参考に説明する。

<a href="comments.html"
   th:href="@{/product/comments(prodId=${prod.id})}"
   th:if="${not #lists.isEmpty(prod.comments)}">view</a>

これは、#lists.isEmpty(prod.comments)prod.commentsが空か否か判断し、空の場合はtrueになるが、notが付いているのでfalseになる。つまり、prod.commentsが空の場合は何も表示されないが、空でない場合はリンクth:href="@{/product/comments(prodId=${prod.id})}"が表示される。
補足:not!と書いても良い。
th:unlessth:ifと反対の動作をする属性で、上記のコードは下記のように書ける。

<a href="comments.html"
   th:href="@{/comments(prodId=${prod.id})}"
   th:unless="${#lists.isEmpty(prod.comments)}">view</a>

オブジェクトを使ってコントローラとビューで値を共有する

次のページに記載しています。

定型文

<html xmlns:th="http://www.thymeleaf.org">

IDEがth:*属性に対してエラーを出さないようにする定型文。テンプレートに対して意味はない。

公式で確認できなかった属性やユーティリティメソッド等

Thymeleaf公式ページでは確認できなかったが、使用できる属性やユーティリティメソッド等をまとめてます。

エラー関係

次のサイトが参考になった。使用例のコードも記載されています。

th:errorclass : エラー時のみ設定されるクラス属性。テキストの枠を赤くしたりなどなど
#fields.hasErrors(フィールド名) : エラーが発生したかどうか。
th:errors(フィールド名) : エラーメッセージの表示。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?