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のそれぞれがどのように連携しているのかを意識して設計することが大切です。
まとめ
今回の記事では、Spring Boot開発において非常に重要な役割を果たすThymeleaf(タイムリーフ)とJavaScriptの動的連携について詳しく解説してきました。サーバーサイドのJavaで保持しているデータを、クライアントサイドのJavaScriptへ安全かつスムーズに受け渡す方法は、動的なWebアプリケーションを構築する上で欠かせないテクニックです。
Thymeleaf連携の重要ポイントを再確認
ThymeleafとJavaScriptを連携させる際、最も核となるのはth:inline="javascript"という属性です。これを使用することで、通常は静的なHTMLとして出力されるファイルの中に、Javaの変数をJavaScriptの変数として「注入」することが可能になります。
特に、開発現場で多用されるのがオブジェクトやリスト(配列)の受け渡しです。Thymeleafは優秀なテンプレートエンジンであるため、JavaのListやMap、あるいは独自のエンティティクラスを、JavaScriptが理解できるJSON形式に自動で変換してくれます。これにより、フロントエンド側でグラフを表示したり、動的なドロップダウンリストを作成したりといった高度なUI実装が容易になります。
ここで、実際に「ユーザーリスト」をJava側で作成し、それをJavaScriptで受け取ってコンソールや画面に反映させる一連の流れをおさらいしましょう。pleiades環境などでプロジェクトを作成し、Gradleでビルドする際、以下のコードを参考にしてください。
@Controller
public class SummaryController {
@GetMapping("/summary")
public String summaryPage(Model model) {
// 文字列データの準備
model.addAttribute("pageStatus", "学習完了");
// リストデータの準備(JavaScript側で配列として扱える)
List<String> steps = List.of("環境構築", "Model連携", "JSインライン記述", "動作確認");
model.addAttribute("learningSteps", steps);
// 数値データの準備
model.addAttribute("totalScore", 100);
return "summary_view";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Thymeleaf連携のまとめ</title>
</head>
<body>
<h1>学習のまとめ画面</h1>
<p>現在のステータス:<span th:text="${pageStatus}">不明</span></p>
<script th:inline="javascript">
// Thymeleaf変数をJS変数へ代入
// 文字列の場合はコメント構文を使うと、JS単体でのプレビュー時にもエラーになりにくい
let status = /*[[${pageStatus}]]*/ "default";
let score = [[${totalScore}]];
let stepList = [[${learningSteps}]];
console.log("ステータス: " + status);
console.log("スコア: " + score);
// 配列の中身をループで回す
stepList.forEach((step, index) => {
console.log((index + 1) + "番目のステップ: " + step);
});
// 動的な処理の例
if (score === 100) {
alert("全ステップの学習が完了しました!次は実践プロジェクトに挑戦しましょう。");
}
</script>
</body>
</html>
SEOとユーザビリティを意識した設計
Webサイトの制作において、Thymeleafを使うメリットは単に「Javaとつながる」ことだけではありません。検索エンジン(Google等)にヒットしやすくするためには、**「初期表示時に必要な情報をHTMLとしてレンダリングしつつ、その後の動的な挙動はJavaScriptに任せる」**というハイブリッドなアプローチが有効です。
例えば、ページのタイトルや重要な説明文はth:textを使ってHTMLとしてしっかり出力し、一方で詳細なグラフデータやユーザー個別の設定値などはth:inline="javascript"で渡してクライアントサイドで処理させる、といった具合です。これにより、SEOの恩恵を受けつつ、リッチなユーザー体験を提供できるのです。
今後の学習ステップ:デバッグと最適化
これから実務でThymeleafを使っていく中で、もし値がうまく渡らない場合は、まずはブラウザのデベロッパーツール(F12)の「ソース」タブを確認してください。Thymeleafが正しくレンダリングしていれば、そこには[[${...}]]ではなく、実際の値("学習完了"など)が埋め込まれているはずです。
また、大規模なデータを扱う際は、すべてのデータを一度にThymeleafで渡すのではなく、必要に応じてAjaxやFetch APIを用いた非同期通信(API連携)と組み合わせることも検討しましょう。Thymeleafはあくまで「最初の一歩」としてのデータ受け渡しに非常に強力なツールとなります。
Javaエンジニアとして、フロントエンドとの境界線をスムーズにつなぐこのスキルは、バックエンド開発の幅を大きく広げてくれる武器になります。pleiadesの環境を活用し、何度もコードを書いて体で覚えていきましょう。
生徒
「先生、今回の内容でThymeleafとJavaScriptの連携がかなりクリアになりました!特にth:inline="javascript"の便利さに感動しています。」
先生
「それは良かった!今まではJavaはJava、JavaScriptはJavaScriptと完全に切り離して考えていたかもしれないけれど、Thymeleafがその橋渡しをしてくれるのがわかったかな?」
生徒
「はい。コントローラでmodel.addAttributeした値が、そのままスクリプトの中で変数として使えるのは魔法みたいですね。でも、さっき練習していたら、日本語の文字列が文字化けしたり、うまく認識されないことがあったんです。」
先生
「ああ、それは初心者がよく通る道だね。JavaScriptの中で文字列を扱うときは、let msg = /*[[${message}]]*/ 'default';という風にコメント構文で囲むのがコツだよ。こうするとThymeleafが適切にクォーテーションを補完して、エスケープもしてくれるんだ。」
生徒
「なるほど、コメントを使うことで、ブラウザで直接HTMLファイルを開いたときのエラーも防げるんですね。あと、配列を渡したときに勝手にJavaScriptの配列(`[]`)形式に変換されたのにも驚きました。」
先生
「そうなんだ。Thymeleaf内部でJSON変換に近いことをやってくれるから、複雑なオブジェクトリストもforEachとかで簡単に回せるようになる。Java側でデータを整形してから渡せば、フロントエンドのコードもスッキリするよ。」
生徒
「すごく開発効率が上がりそうです。これなら、サーバーから持ってきた在庫状況によって、ボタンの色を変えたり非活性にしたりするのも簡単そうですね!」
先生
「その通り!ただし注意点として、あんまり大きなデータをJavaScriptの中に埋め込みすぎると、HTMLファイルのサイズが肥大化して読み込みが遅くなることもある。大量のデータを扱うときは、今回の方法とAPI通信をうまく使い分けるのがプロの技だよ。」
生徒
「状況に応じて使い分けるんですね。まずは今回教わった基本をしっかりマスターして、pleiadesでいろいろなパターンの画面を作ってみます!」
先生
「その意気だね。もしエラーが出たら、ブラウザのコンソールを真っ先に確認すること。頑張って!」