第5章 Thymeleafの利用

5.6 構文・インライン・レイアウト

テンプレートエンジンの基本は、テンプレートの中にコントローラー側で用意した値をはめ込んでレンダリングすることです。単純に値をはめ込むだけなら、ここまでの説明でほぼ行なえるようになりました。

が、Thymeleafには、もっと高度な値の組み込み方を行うための仕組みが色々と用意されています。例えば、既に試した「th:if」のようなプログラミング言語の構文に相当する機能、HTMLやJavaScriptのコードをダイナミックに埋め込んだり、OGNLの式を展開してから組み込むような機能、複数のテンプレートを組み合わせてレイアウトするための機能などです。 こうした、「更に一歩上を行く使いこなし」のための機能について、ここでまとめて説明することにしましょう。

5.6.1 多項分岐の「th:switch」

th:if などは真偽値を使った条件分岐であり、基本的に「二者択一」の表示を行うものでした。では、3つ以上に分岐をさせたい場合はどうするのでしょうか。 このような場合に用いられるのが、「th:switch」です。以下のように記述します。

th:switch は、指定された条件式の値をチェックし、その内側にある th:case から同じ値のものを探してそのタグだけを出力します。

では、これも簡単なサンプルで試してみましょう。コントローラー側から値を渡し、それを元に表示をさせるサンプルを考えて見ます。今回は、月を示す整数を渡すと、そのつきの季節を表示する(例えば、4と送ると「4 – 春」と表示される)ようにしてみましょう。

【ファイル名:ThymeleafController.java】
  // 「/thymeleaf」へアクセスがあった場合
  @GetMapping("/thymeleaf")
  public ModelAndView thymeleaf(ModelAndView mav) {
    // リンク用サンプル
    mav.addObject("user_id", 999);
    // 選択オブジェクト用サンプル
    User user = new User("神田太郎", 25);
    mav.addObject("user", user); 
    HTMLコード出力用サンプル
    mav.addObject("html", "<h3>HTMLコードを出力しました。</h3>");
    // 多項分岐用サンプル
    mav.addObject("month", 1);
    // 画面に出力するViewを指定
    mav.setViewName("thymeleaf/howto");
    // ModelとView情報を返す
    return mav;
  }
  

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。 URL:http://localhost:8080/thymeleaf


図 5.6 1:月の値をコントローラーから渡すとその季節が表示される

コントローラー側では「month」の名前で「1」という値を渡しているだけですね。

【ファイル名:ThymeleafController.java】
  // 多項分岐用サンプル
  mav.addObject("month", 1);
  

対して、今回のポイントであるテンプレート側の「th:switch」を見てみましょう。ここでは、以下のようにして「month」の値に応じて表示するメッセージを設定しています。

【ファイル名:howto.html】

th:switch=”${month}” とすることにより、この<div>タグの内部では、month の値と同じ th:case のタグだけが表示されるようになります。<p>タグを見ると、th:case=”1” th:text=”|${month} – 冬|” というように、th:case の値と、th:text によるメッセージが用意されています。th:case=”1” ならば、${month} の値が 1 の時にこのタグが表示される、というわけです。

また、一番最後に th:case=”*” という記述が用意されているのに気が付くでしょう。これは、ワイルドカードを使った指定です。つまり、どの th:case にも合致しなかったすべての値を、ここでキャッチするようになっているのです。Java の switch における default: に相当するものと考えてよいでしょう。

5.6.2 繰り返しの「th:each」

条件分岐があるなら、当然、繰り返しのための属性もあります。これは「th:each」で、以下のように記述します。

th:each では、配列などを値として用意します。が、ただ配列だけを書くのではなく、例えば “value : ${list}” といった具合に、新たな変数名と併せて記述します。これにより、コロンの後にあるリストから順に値を取り出し、コロン前の変数に代入するようになります。
このタグの内部では、コレクションから値が代入された変数を利用して値の出力などが行なえます。
では、まずコントローラー・テンプレートを修正していきましょう。

【ファイル名:ThymeleafController.java】

【ファイル名:howto.html】】

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8080/thymeleaf

図 5.6 2:データの一覧が表示される

まず、コントローラー側から見ていきます。ここでは、ArrayListインスタンスを作成し、そこに User 配列の形でデータを保管しています。これをテンプレート側に users として渡し、表示させようというわけです。

【ファイル名:ThymeleafController.java】
  //繰り返し用サンプル
  ArrayList<User> users = new ArrayList<User>();
  users.add(user);
  users.add(new User("神田次郎", 20));
  users.add(new User("神田花子", 15));
  mav.addObject("users", users);
  

テンプレート側では<table>タグの部分を見てみましょう。

【ファイル名:howto.html】

<tr>タグに th:each=”data : ${users}” という形で th:each が用意されています。これで、users から順に値を取り出しては data に代入する、という繰り返し処理が実行されます。
また、併せて th:object=”${data}” も記述されていることに気付くと思います。これにより 繰り返しの内部でも オブジェクトが持つプロパティ名のみを *{ } で書けばいいようにしています。

このように、「繰り返し出力したいタグ」に、th:each は設定するのです。

5.6.3 テンプレートフラグメント

Webページは、常に1つのファイルだけで作成しなければいけないわけではありません。例えば、ヘッダーやフッター、メニューといった部品を別ファイルとして用意し、それらを組み合わせてページ全体のレイアウトを作成する、ということもよくあります。

テンプレートで、このように「複数のファイルを組み合わせてページを構成する」ということを行ないたい場合、利用されるのが「テンプレートフラグメント」です。これは、あるファイルの中に「フラグメント」(そこだけ切り取って扱えるようにした部品)として記述されている部分を、別のテンプレートの指定した場所にはめ込む技術です。
これは、部品となるファイルと、それを組み込む側の両方を用意する必要があります。簡単に整理しておきましょう。

■部品となるテンプレート

部品として用意するテンプレート側には、th:fragment という属性を指定したタグを用意します。値には、このフラグメントに付ける名前を指定します。これにより、このタグの部分がフラグメントとして他に組み込めるようになります。

■組み込む側

th:include を用意し、そこに部品となるテンプレートの名前とフラグメント名を記述します。これで、このタグの部分に指定のフラグメントがコピーされます。

では、実際にやってみましょう。まずは、新たにテンプレートファイルを用意しましょう。

1

「src/main/resources」パッケージの「templates」>「thymeleaf」内に「fragment.html」を作成

2

2で作成した「fragment.html」ファイルに以下に示すソースコードを記述する

【ファイル名:fragment.html】

続けて、テンプレート側の修正も行ないます。

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8080/thymeleaf

図 5.6 3:fragment.htmlに用意したフラグメントがページ内に組み込まれた形で表示される

まずは、今回作成した fragment.html のソースコードから見ていきましょう。
ここでは、2箇所のフラグメントを設定しています。1つは、<head>内にある<style>タグ。もう1つは、<body>にある<div>タグです。それぞれ以下のように指定してあります。

【ファイル名:fragment.html】

これで、”sample_style” と “sample_contents” という2つのフラグメントが用意できました。フラグメントは、このように1つのファイル内でいくつも指定することができます。

では、フラグメントを組み込む側である howto.html を見てみましょう。
ここでは、<head>内の<style>タグと、<body>内最後の<div>タグにそれぞれフラグメントを組み込んでいます。

【ファイル名:howto.html】

ファイルの指定は「thymeleaf/fragment」となっていますね。これは「thymeleaf」フォルダ内の「fragment.html」であることを示しています。拡張子まで書く必要はありません。これで fragment.html に用意したコンテンツと、そこで使用するスタイルシートが組み込まれて表示されます。

フラグメントの面白いところは、「部品となる側も、普通のテンプレートファイルとして用意できる」という点です。つまり、フラグメント用に特別なものを用意するわけではなく、普通のテンプレートとして利用できるものの一部にフラグメントを指定するだけなのです。

ですから、普通に表示するコンテンツの一部に th:fragment を指定しておき、必要に応じてそれらを1つのページに集めて表示する、といったことも可能です。いろいろな利用の仕方が考えられますね!

NEXT>> 5.7 本章のまとめ