Thymeleaf javascript 動的連携のテクニック|初心者でもわかるデータ受け渡しの基本
新人
「先輩、ThymeleafとJavaScriptってどうやって連携するんですか?Javaの値を画面のスクリプトで使いたいんですけど…」
先輩
「良い質問だね。ThymeleafはJavaのテンプレートエンジンとして動作して、サーバー側の値をHTML内に埋め込めるんだ。JavaScriptとの動的連携も、その仕組みをうまく使えば簡単にできるよ。」
新人
「なるほど!でも、ThymeleafってHTMLを作るだけのものじゃないんですか?」
先輩
「確かに基本はテンプレートエンジンだけど、実はJavaScriptとも連携できる機能があるんだ。まずはThymeleafそのものの仕組みから見ていこう。」
1. Thymeleafとは?テンプレートエンジンとしての基本
Thymeleaf(タイムリーフ)は、Spring Frameworkでよく使われるテンプレートエンジンです。サーバーサイドのJavaコードで作成したデータをHTMLに埋め込み、動的なWebページを生成します。特徴は「HTMLをそのままブラウザで開いても構文エラーにならない」ことです。これにより、デザイナーとエンジニアが同じファイルを扱いやすくなります。
Thymeleafのテンプレートは、プレーンなHTMLに特別な属性(th:text、th:eachなど)を加えるだけで、サーバー側の値を反映できます。例えば、次のようなサンプルで変数を表示できます。
<p th:text="${message}">ここにメッセージが表示されます</p>
このように、Thymeleafを使うとJavaで渡したデータを直接HTMLに埋め込むことができます。次に、どのようにしてJavaの値をテンプレートに渡すのかを見ていきましょう。
2. JavaとThymeleafを使って画面を動的に作る仕組み
Springでは、@Controllerクラスを使ってサーバー側でデータを用意し、それをThymeleafのテンプレートに渡します。@RestControllerは使わず、あくまで画面表示を目的にした構成です。開発環境はpleiadesを使い、Gradleでビルドします。
コントローラの基本構成は次のようになります。
@Controller
public class SampleController {
@GetMapping("/sample")
public String showSamplePage(Model model) {
model.addAttribute("message", "ThymeleafとJavaScriptの連携を学ぼう!");
model.addAttribute("count", 5);
return "sample";
}
}
上記のコードでは、Modelに値を入れてテンプレートに渡しています。HTML側では${message}として参照可能です。ThymeleafはこれをHTMLに埋め込み、実際のページとしてブラウザに返します。
こうした仕組みを理解しておくと、次のステップであるJavaScriptとの連携がぐっとわかりやすくなります。
3. JavaScriptとThymeleafを連携させる目的
Thymeleafのテンプレート内では、サーバーサイドの値をHTMLやJavaScriptに渡すことができます。これにより、ページを再読み込みせずに動的な動作を行ったり、サーバーのデータを使ってクライアント側でアニメーションや動的表示を制御したりできます。
例えば、商品一覧ページで在庫数をJavaScriptで制御したい場合、サーバー側から在庫情報をThymeleaf経由で渡し、JavaScriptで描画します。このように、ThymeleafとJavaScriptを組み合わせることで、動的なUIをシンプルに構築できます。
テンプレート内でJavaScriptに変数を渡す基本構文は次のようになります。
<script th:inline="javascript">
let count = [[${count}]];
let message = /*[[${message}]]*/ "デフォルトメッセージ";
console.log(message + " カウント:" + count);
</script>
th:inline="javascript"を指定すると、ThymeleafがJavaの変数をJavaScriptコード内に埋め込みます。この仕組みにより、サーバーからの値をクライアントスクリプトで扱えるようになります。
こうした「ThymeleafからJavaScriptへの動的連携」は、特にSpring MVCアプリケーションで強力です。次の記事では、実際にこの構文を使って動的にHTMLを生成したり、イベントと組み合わせて動作させる方法を解説していきます。
4. ThymeleafからJavaScriptへ変数を渡す方法(th:inline="javascript"の使い方)
ThymeleafとJavaScriptを連携させるときに欠かせないのが、th:inline="javascript"属性です。これは、Thymeleafのサーバーサイド変数をJavaScriptのコード内で安全に展開するための機能です。通常のHTML属性ではなく、JavaScriptのスクリプトブロック内に直接値を埋め込むことができます。
まず、基本的なサンプルを見てみましょう。
<script th:inline="javascript">
let username = [[${username}]];
let userAge = [[${age}]];
console.log("ユーザー名:" + username + " 年齢:" + userAge);
</script>
このように記述すると、コントローラで設定したusernameやageの値がHTMLのレンダリング時に展開され、JavaScript変数として利用できるようになります。例えば、次のようなコントローラを用意しておきます。
@Controller
public class UserController {
@GetMapping("/user")
public String showUserPage(Model model) {
model.addAttribute("username", "田中太郎");
model.addAttribute("age", 28);
return "user";
}
}
この状態でページを開くと、JavaScript側のusername変数には「田中太郎」が、userAgeには28が埋め込まれます。つまり、サーバーで生成した値をそのままフロントエンド側で扱えるということです。
また、文字列を安全に埋め込むためには、コメント構文を使う方法もあります。以下のように記述すると、文字列が空白や記号を含んでいても正しく扱えます。
<script th:inline="javascript">
let welcomeMessage = /*[[${welcomeText}]]*/ "デフォルトメッセージ";
</script>
Thymeleafはこのコメント部分を自動的に変換してくれるため、HTMLの構文を崩さずにJavaScriptコードへ安全に値を埋め込むことができます。
5. JavaScriptでThymeleafの値を動的に扱う方法(オブジェクトや配列)
単純な変数だけでなく、配列やオブジェクトをJavaScript側で扱いたい場合もあります。ThymeleafはJSON形式のデータをそのままJavaScriptに渡すことができるので、動的なUIを作るのに非常に便利です。
たとえば、サーバーから複数の商品情報を渡してJavaScriptでリスト表示する場合、次のように記述できます。
@Controller
public class ProductController {
@GetMapping("/products")
public String showProducts(Model model) {
List<String> products = List.of("パソコン", "スマートフォン", "タブレット");
model.addAttribute("productList", products);
return "products";
}
}
テンプレート側では、th:inline="javascript"を利用して配列として受け取ります。
<script th:inline="javascript">
let products = [[${productList}]];
products.forEach(function(item) {
console.log("商品:" + item);
});
</script>
この例では、List型のデータが自動的にJavaScriptの配列に変換されます。Thymeleafは型を意識せずとも適切にJSON変換を行うため、特別な処理は不要です。さらに、配列だけでなく複雑なオブジェクトも扱えます。
例えば、商品名と価格を含むオブジェクトのリストを渡す場合、次のように記述します。
@GetMapping("/items")
public String showItems(Model model) {
List<Map<String, Object>> items = new ArrayList<>();
Map<String, Object> item1 = Map.of("name", "ノートPC", "price", 120000);
Map<String, Object> item2 = Map.of("name", "スマホ", "price", 85000);
items.add(item1);
items.add(item2);
model.addAttribute("items", items);
return "items";
}
テンプレート側では次のようにJavaScriptで受け取れます。
<script th:inline="javascript">
let items = [[${items}]];
items.forEach(function(obj) {
console.log(obj.name + ":" + obj.price + "円");
});
</script>
このように、サーバーサイドで用意したリストやオブジェクトをJavaScriptで動的に処理することで、ページ全体を再描画せずに更新することができます。特に在庫やユーザー情報などを非同期的に扱う場面で効果的です。
6. @ControllerクラスからHTMLテンプレートへデータを渡す流れ
ここまでの内容をまとめると、ThymeleafとJavaScriptの連携は次の三段階で構成されています。
- Javaの
@Controllerでデータを用意する - Modelオブジェクトに値を追加してテンプレートに渡す
- Thymeleafのテンプレートで
th:inline="javascript"を使い、JavaScriptに値を受け渡す
実際の一連の流れを、シンプルなサンプルで見てみましょう。
@Controller
public class InfoController {
@GetMapping("/info")
public String showInfo(Model model) {
model.addAttribute("siteTitle", "Thymeleafデータ連携のサンプル");
model.addAttribute("visitors", 120);
return "info";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="${siteTitle}">ThymeleafとJavaScriptの連携</title>
</head>
<body>
<h3 th:text="${siteTitle}">タイトル</h3>
<script th:inline="javascript">
let title = [[${siteTitle}]];
let visitors = [[${visitors}]];
alert("ページタイトル:" + title + " 訪問者数:" + visitors);
</script>
</body>
</html>
このように、コントローラで設定した値をThymeleafのHTML内に埋め込み、さらにJavaScriptでも扱うことができます。これが「サーバーサイドとクライアントサイドを橋渡しする仕組み」です。
特にpleiades+Gradle環境では、設定やビルドが簡単で、すぐに実行結果を確認できます。@ControllerとThymeleafの連携を理解すると、複雑なJavaScript処理も柔軟に実装できるようになります。
次の記事では、実際にThymeleafで作った値をボタンクリックやフォーム送信イベントと組み合わせて動かす方法を紹介します。これにより、さらに実践的な動的Webページ開発ができるようになります。
7. 実践例:Thymeleafで生成した値をJavaScriptで動的に表示する
ここでは実際に、サーバーで生成した値をThymeleaf経由でJavaScriptに渡し、ブラウザ上で動的に表示する例を見ていきましょう。開発環境はこれまでと同じく、pleiades+Gradleで構築し、@Controllerクラスからデータを渡します。
まず、サーバー側でメッセージと数値を用意します。コントローラではModelを使ってテンプレートへ値を渡します。
@Controller
public class MessageController {
@GetMapping("/dynamic")
public String showDynamicPage(Model model) {
model.addAttribute("greeting", "こんにちは、Thymeleafの世界へようこそ!");
model.addAttribute("count", 10);
return "dynamic";
}
}
次に、HTMLテンプレートでJavaScriptを使って受け取った値を動的に表示します。ここではth:inline="javascript"を使用して、サーバーからの値をJavaScriptに埋め込みます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ThymeleafとJavaScriptの動的連携例</title>
</head>
<body>
<h3>動的メッセージ表示</h3>
<div id="messageArea"></div>
<script th:inline="javascript">
let greeting = [[${greeting}]];
let count = [[${count}]];
document.getElementById("messageArea").innerText = greeting + " カウント:" + count;
</script>
</body>
</html>
このサンプルでは、コントローラから渡された文字列と数値がHTML内のJavaScriptに展開され、ページ読み込み時に動的にメッセージが表示されます。つまり、Java側で変更したデータがそのままJavaScriptに反映されるという流れです。これが「ThymeleafとJavaScriptの動的連携」の基本です。
また、JavaScriptでDOM要素を操作することで、サーバーのデータを画面に即座に反映できます。ページ全体を再読み込みすることなく、部分的な更新が可能になります。
8. フォーム送信やボタンクリックなどのイベントと連携する方法
次に、Thymeleafで渡したデータをユーザー操作と組み合わせる方法を学びましょう。ボタンをクリックしたときにJavaScriptで値を参照し、動的に内容を変える例を紹介します。
まず、コントローラではページ表示用のデータを準備します。
@Controller
public class EventController {
@GetMapping("/event")
public String showEventPage(Model model) {
model.addAttribute("info", "初期メッセージ:ボタンを押すとメッセージが変わります。");
model.addAttribute("newMessage", "ThymeleafとJavaScriptの連携が成功しました!");
return "event";
}
}
テンプレート側では、ボタンのクリックイベントでメッセージを切り替えます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Thymeleafとイベント連携</title>
</head>
<body>
<p id="displayArea" th:text="${info}">ここにメッセージが表示されます</p>
<button id="changeBtn">メッセージを変更</button>
<script th:inline="javascript">
let newMessage = [[${newMessage}]];
document.getElementById("changeBtn").addEventListener("click", function() {
document.getElementById("displayArea").innerText = newMessage;
});
</script>
</body>
</html>
この構成では、サーバー側で設定したメッセージがThymeleaf経由でJavaScriptに渡され、ユーザーのクリック操作で表示内容を更新します。ポイントは、HTMLテンプレート内のJavaScriptがサーバー変数を直接参照できるという点です。
さらに、フォーム送信時にも同様の仕組みを利用できます。フォームの入力値をサーバーに送る前に、JavaScriptで確認したり動的にメッセージを切り替えたりすることで、ユーザー体験を向上させられます。
このように、イベントと連携させることで、Thymeleafによる「静的HTML生成」と「動的スクリプト制御」を自然に融合させることができます。
9. よくあるエラーとトラブルシューティング(undefinedや値が渡らない場合など)
ThymeleafとJavaScriptの動的連携では、初心者がつまずきやすいポイントがいくつかあります。特に多いのが、JavaScript側で「undefined」や「null」が出てしまうケースです。ここでは、その原因と解決策を順に説明します。
① 変数がundefinedになる場合
最もよくあるのは、Thymeleafで渡す変数名の不一致です。コントローラ側でmodel.addAttribute("userName", "山田花子");と設定した場合、テンプレート側でも同じ${userName}を指定しなければなりません。名前が少しでも違うと、JavaScriptに正しく展開されず、undefinedになります。
② th:inline="javascript"を忘れている
JavaScriptブロックでThymeleaf変数を使う際には、必ずth:inline="javascript"を指定する必要があります。これがないと、Thymeleafが変数を解釈せず、JavaScript内にそのまま[[${変数}]]という文字列が残ってしまいます。
③ 値が文字列として扱われていない
文字列の変数を渡すときは、コメント構文を使って安全に埋め込むのがおすすめです。特に日本語や特殊文字を含む場合、通常の構文だと正しくパースされないことがあります。
<script th:inline="javascript">
let message = /*[[${textMessage}]]*/ "";
</script>
このようにコメント形式を使うことで、Thymeleafが自動的にエスケープ処理を行い、JavaScript内で安全に展開されます。
④ そもそも値が渡っていない
モデルに値を追加していない場合も見落としやすいミスです。コントローラ側でmodel.addAttribute()を呼び忘れると、テンプレートでは何も受け取れません。値を確認するには、一時的にth:textでHTML内に出力してチェックするとよいでしょう。
<p th:text="${textMessage}">デバッグ用の出力</p>
こうした確認を行うことで、どの段階で値が失われているのかを判断できます。
⑤ JavaScriptの実行順序
Thymeleaf変数を参照するJavaScriptは、HTML要素が生成された後に実行する必要があります。スクリプトをhead内に書くと、まだDOMが生成されていない状態で要素を参照しようとしてエラーになります。そのため、基本的には</body>の直前にスクリプトを配置するようにしましょう。
これらのトラブルシューティングを理解しておけば、ThymeleafとJavaScriptのデータ受け渡しで問題が起きても慌てずに対処できます。エラーの多くは、構文や変数名、処理の順序に原因があります。
特にpleiades環境では、Gradleビルドのキャッシュが残って古いテンプレートが表示されることもあります。その場合は、プロジェクトをクリーンビルドして再実行すると正しい結果が確認できます。
以上のように、ThymeleafとJavaScriptの動的連携を正しく理解しておくことで、データ受け渡しのエラーを防ぎ、安定したアプリケーション開発が可能になります。コントローラ、テンプレート、JavaScriptのそれぞれがどのように連携しているのかを意識して設計することが大切です。