Thymeleaf javascript引数渡しの基本的なやり方|初心者でもわかるSpring連携ガイド
新人
「先輩、ThymeleafでJavaScriptに値を渡す方法が知りたいんですけど、どうすればいいんですか?」
先輩
「いいね!ThymeleafはSpringとよく使われるテンプレートエンジンで、Javaの値をHTMLやJavaScriptに埋め込むことができるんだよ。」
新人
「テンプレートエンジンって、JavaScriptとどうやってつながるんですか?」
先輩
「それじゃあ、まずThymeleafの基本から説明しよう。そのあとで、JavaScriptへ値を渡す方法を実際に見ていこうか。」
1. Thymeleafとは何か(テンプレートエンジンの概要)
Thymeleaf(タイムリーフ)は、Spring Frameworkでよく使われるテンプレートエンジンです。テンプレートエンジンとは、サーバーサイドでJavaオブジェクトの値をHTMLに埋め込む仕組みのことです。たとえば、コントローラで用意したデータをHTMLに表示する場合、Thymeleafを使えば静的なHTMLを動的に変化させることができます。
このテンプレートエンジンは、HTMLをベースにしているため、ブラウザで開いても崩れにくく、デザイナーとエンジニアが同じテンプレートを扱えるという利点があります。特に、Spring BootやSpring MVCと組み合わせて使うと、Webアプリ開発が非常に効率的になります。
今回は、pleiades+Gradle構成のSpringプロジェクトを前提に、@Controllerクラスで値を渡す方法を紹介します。
@Controller
public class SampleController {
@GetMapping("/example")
public String example(Model model) {
model.addAttribute("message", "Hello Thymeleaf!");
return "example";
}
}
このようにModelにデータを入れると、Thymeleaf側でその値を取り出してHTMLに反映できます。
2. JavaScriptとの連携の基本(Thymeleafでスクリプトに値を渡す仕組み)
Thymeleafは単にHTMLに値を埋め込むだけでなく、JavaScriptとの連携も得意です。サーバーサイドで用意した変数を、フロントエンドのスクリプトで利用したいケースはよくあります。たとえば、ログイン中のユーザー名や設定情報をJavaScriptに渡したい場合などです。
Thymeleafでは、th:inline="javascript"という属性を使うことで、JavaScript内にサーバー変数を直接埋め込むことができます。この仕組みを理解することで、サーバーからのデータを動的に扱えるようになります。
<script th:inline="javascript">
let message = [[${message}]];
console.log(message);
</script>
このように書くと、SpringのModelに登録したmessageがJavaScript変数に展開されます。実際にブラウザで開くと、次のように表示されます。
Hello Thymeleaf!
このように、サーバーサイドからクライアントサイドへ自然にデータを受け渡すことができるのがThymeleafの魅力です。
3. th:inline="javascript" の基本的な役割と使い方
このth:inline="javascript"属性は、Thymeleafテンプレートの中でJavaScriptを埋め込むときに使用します。通常、ThymeleafはHTMLとして出力することを前提としていますが、この指定を入れることでスクリプト部分でも式展開が可能になります。
たとえば、複数の値を渡したい場合、配列やオブジェクト形式で記述することもできます。
<script th:inline="javascript">
let user = {
name: [[${user.name}]],
age: [[${user.age}]]
};
console.log(user);
</script>
この例では、サーバーサイドで用意したuserオブジェクトからnameとageを取得し、JavaScriptでそのまま使えるようにしています。Spring MVCでは、次のようにコントローラを定義します。
@Controller
public class UserController {
@GetMapping("/user")
public String user(Model model) {
User user = new User("Taro", 25);
model.addAttribute("user", user);
return "user";
}
}
このようにth:inlineを使うと、JavaScript内で値を安全に展開できます。ただし、文字列を扱う際は必ずクォーテーションで囲うように注意しましょう。クォーテーションが抜けると、JavaScript構文エラーが発生します。
また、[[${...}]]は変数の値を直接展開し、[(...)]は文字列として扱うという違いがあります。この違いを理解することで、ThymeleafとJavaScriptの連携をより正確に行うことができます。
4. 変数をJavaScriptに渡す実例(モデルから値を受け取る方法)
ここでは、Spring MVCのコントローラからJavaScriptへ値を渡す具体的な例を紹介します。前回の解説で紹介したように、ThymeleafではModelを使ってサーバー側からデータをテンプレートに渡します。そして、テンプレート上でth:inline="javascript"を指定することで、その値をスクリプト内に埋め込むことができます。
まず、コントローラクラスを用意して、サーバーサイドの変数を設定します。開発環境はpleiades上でGradleプロジェクトを作成し、@Controllerを使う構成を前提としています。
@Controller
public class MessageController {
@GetMapping("/showMessage")
public String showMessage(Model model) {
String info = "サーバーから渡されたメッセージです。";
model.addAttribute("info", info);
return "showMessage";
}
}
このコントローラでは、infoという文字列をモデルに追加し、それをshowMessage.htmlテンプレートで利用できるようにしています。
次に、Thymeleafテンプレート側でJavaScriptに変数を渡してみましょう。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ThymeleafとJavaScriptの連携</title>
</head>
<body>
<h3 th:text="${info}">メッセージを表示します</h3>
<script th:inline="javascript">
let infoMessage = [[${info}]];
alert(infoMessage);
</script>
</body>
</html>
この例では、サーバーで設定したinfoの値がJavaScript変数infoMessageに展開され、ページを開くとアラートウィンドウに「サーバーから渡されたメッセージです。」と表示されます。これはThymeleafの[[${...}]]構文を利用した代表的な例です。
このように、Spring MVCとThymeleafの組み合わせでは、サーバーで生成されたデータをJavaScriptに渡す処理が非常にシンプルに記述できます。
5. 複数の値をオブジェクト形式で渡す方法
次に、複数の値を一度にJavaScriptへ渡す方法を紹介します。実際の開発では、ユーザー情報や設定値などをまとめて受け渡したい場面が多くあります。そのような場合は、オブジェクト形式でデータをまとめて渡すと管理しやすくなります。
まず、Spring側のコントローラで複数の値をモデルに格納します。
@Controller
public class MultiValueController {
@GetMapping("/multi")
public String multi(Model model) {
model.addAttribute("username", "Hanako");
model.addAttribute("age", 28);
model.addAttribute("email", "hanako@example.com");
return "multi";
}
}
このように、username・age・emailの3つの属性を設定します。Thymeleafテンプレートでは、これらをオブジェクトとしてまとめて受け取ることができます。
<script th:inline="javascript">
let user = {
name: [[${username}]],
age: [[${age}]],
email: [[${email}]]
};
console.log(user);
</script>
このコードでは、Spring MVCのモデルから受け取った値をJavaScriptオブジェクトに変換しています。ブラウザの開発者ツールでコンソールを確認すると、次のように出力されます。
{name: 'Hanako', age: 28, email: 'hanako@example.com'}
このように、複数の値をオブジェクト形式で受け渡すことで、JavaScript側での処理がわかりやすくなります。また、ThymeleafはSpringと密接に連携しているため、値の整合性が取りやすく、安全なデータ埋め込みが可能です。
さらに、もし配列形式で渡したい場合は、次のように書くこともできます。
<script th:inline="javascript">
let fruits = [[${fruitsList}]];
console.log(fruits);
</script>
このように配列を扱うことで、JavaScriptのループ処理や動的な描画に活用できるようになります。
6. th:inline="javascript"を使う際の注意点(エスケープや文字列の扱い)
th:inline="javascript"を使うと非常に便利ですが、初心者がつまずきやすい注意点もいくつかあります。特に、文字列の扱いやエスケープ処理には注意が必要です。
まず、Thymeleafの[[${...}]]構文は、数値や真偽値などのプリミティブ型ではそのまま出力しますが、文字列の場合は必ずクォーテーションで囲む必要があります。たとえば、次のように書かないとエラーになります。
<script th:inline="javascript">
// NG例
let text = [[${text}]]; // 文字列にクォーテーションがつかない
</script>
この場合、JavaScriptの文法エラーが発生します。正しい書き方は以下のように文字列をクォーテーションで囲うことです。
<script th:inline="javascript">
// OK例
let text = '[[${text}]]';
</script>
また、ThymeleafはHTMLエスケープを自動的に行います。そのため、特殊文字や改行を含むデータをそのままJavaScriptに渡すと、意図しない文字列になることがあります。このような場合は、th:utextやエスケープ無効化の設定を適切に使う必要があります。
さらに、JSON形式で値を扱う場合は、サーバー側でObjectMapperを使ってJSON文字列を生成し、それをThymeleafに渡す方法もあります。この方法なら、JavaScript側でJSON.parse()を使って安全にオブジェクト化できます。
@Controller
public class JsonController {
@GetMapping("/json")
public String json(Model model) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> data = new HashMap<>();
data.put("title", "Spring MVC連携");
data.put("version", 6);
String json = mapper.writeValueAsString(data);
model.addAttribute("jsonData", json);
return "json";
}
}
<script th:inline="javascript">
let data = JSON.parse('[[${jsonData}]]');
console.log(data.title);
</script>
このように、th:inline="javascript"を正しく理解すれば、サーバーサイドからのデータを柔軟に扱うことができ、動的なWebアプリケーションの開発に大きく役立ちます。
7. フォーム入力値をJavaScriptに渡す実践例(イベントとの組み合わせ)
ここからは、ThymeleafとJavaScriptの動的連携をもう少し実践的に見ていきましょう。今回は、ユーザーがフォームに入力した値をJavaScriptで取得し、サーバーへ送信する流れを例にします。初心者の方が混乱しやすい「フォーム入力とJavaScriptの橋渡し」の部分を丁寧に解説します。
新人
「先輩、入力フォームの値ってJavaScriptにどうやって渡すんですか?」
先輩
「いい質問だね。フォームの入力内容は、イベントリスナーを使えばリアルタイムでJavaScript側に渡せるよ。Thymeleaf側で変数を用意しておけば、サーバーとの連携も簡単になるんだ。」
まず、Springの@Controllerを定義します。
@Controller
public class InputController {
@GetMapping("/form")
public String formPage(Model model) {
model.addAttribute("defaultMessage", "初期メッセージです");
return "form";
}
}
次に、ThymeleafテンプレートでフォームとJavaScriptを組み合わせてみましょう。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>フォーム入力値をJavaScriptへ渡す</title>
</head>
<body>
<h3>ThymeleafとJavaScriptの動的連携</h3>
<p th:text="${defaultMessage}"></p>
<input type="text" id="userInput" placeholder="メッセージを入力">
<button id="sendBtn">送信</button>
<script>
document.getElementById("sendBtn").addEventListener("click", function() {
let value = document.getElementById("userInput").value;
alert("入力内容:" + value);
});
</script>
</body>
</html>
このように、イベントを利用すればJavaScriptがユーザーの操作を検知し、入力値を扱えます。さらに、この値をAjax通信でSpringに送信すれば、リアルタイムな動作を実現できます。フォーム入力とイベント処理の理解は、動的Webアプリ開発の第一歩です。
8. Ajax通信でサーバーから値を受け取って描画する応用例
ここでは、JavaScriptのAjax機能とThymeleafを組み合わせ、サーバーから値を非同期で取得して画面に反映する例を紹介します。非同期通信とは、ページを再読み込みせずにサーバーとデータをやり取りする仕組みのことです。
新人
「ページをリロードせずにサーバーの値を取ってこれるんですか?」
先輩
「そうだよ。Springのコントローラを使ってJSONデータを返せば、JavaScript側で受け取って動的に描画できるんだ。」
まずはSpringのコントローラを用意します。
@Controller
public class AjaxController {
@ResponseBody
@GetMapping("/getData")
public Map<String, Object> getData() {
Map<String, Object> map = new HashMap<>();
map.put("status", "OK");
map.put("message", "サーバーからの応答です");
return map;
}
@GetMapping("/ajax")
public String ajaxPage() {
return "ajax";
}
}
次に、ThymeleafテンプレートでAjax通信を行います。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Ajax通信のThymeleaf連携</title>
</head>
<body>
<h3>サーバーと非同期で通信する</h3>
<button id="loadBtn">サーバーから取得</button>
<p id="result"></p>
<script>
document.getElementById("loadBtn").addEventListener("click", function() {
fetch("/getData")
.then(response => response.json())
.then(data => {
document.getElementById("result").textContent = data.message;
})
.catch(error => console.error("通信エラー", error));
});
</script>
</body>
</html>
このサンプルでは、fetch()を使ってSpringのエンドポイント/getDataへアクセスし、返ってきたJSONデータをJavaScriptで処理しています。結果として、ページを再読み込みせずにサーバーのメッセージが画面に表示されます。
この仕組みを利用すれば、Thymeleafをテンプレートとして利用しつつ、JavaScriptによる動的な表示更新を実現できます。これが「Thymeleaf JavaScript引数渡し」を応用した動的連携の実践例です。
9. よくあるエラーとデバッグ方法(値が取れない・undefinedになる原因など)
最後に、ThymeleafとJavaScriptを連携させる際によく発生するエラーと、その解決法を紹介します。特に初心者が悩みやすいのが、「値が取れない」「undefinedが出る」といったトラブルです。
新人
「先輩!変数がundefinedになるんですけど、原因がわかりません!」
先輩
「それはThymeleafの展開順やスクリプトの実行順が関係している可能性があるね。いくつか確認ポイントを見てみよう。」
① th:inlineが指定されていない
JavaScriptにThymeleaf変数を埋め込むには、必ずth:inline="javascript"を指定する必要があります。これがないと、変数がただの文字列として扱われ、JavaScript上ではundefinedになります。
② 文字列のクォーテーション抜け
文字列を渡すときにクォーテーションを忘れると、構文エラーになります。たとえば、let msg = [[${text}]];のように書くと、JavaScriptがそのまま数値扱いしようとして失敗します。正しくはlet msg = '[[${text}]]';とする必要があります。
③ DOMの読み込み順序の問題
JavaScriptが実行されるタイミングでHTML要素がまだ生成されていないと、document.getElementById()がnullを返します。これを防ぐには、スクリプトを</body>直前に置くか、window.onload内で実行します。
④ Ajaxの非同期処理のタイミング
fetch()やXMLHttpRequestでデータを取得する際は、通信が完了する前に値を使おうとするとundefinedになります。Promiseのthen()やasync/awaitを使って、通信完了後に処理を行いましょう。
⑤ Spring側でModelに値が設定されていない
コントローラでmodel.addAttribute()を忘れると、Thymeleafに値が渡りません。JavaScriptに展開される前に空の状態になるため、まずサーバー側の設定を確認することが重要です。
これらを順番に確認していけば、ThymeleafとJavaScript間の引数渡しエラーはほとんど解決できます。特に、Spring MVCとThymeleafの連携では「テンプレートのレンダリング順序」と「JavaScriptの実行タイミング」を意識することが大切です。
新人
「なるほど!JavaScriptのタイミングやクォーテーションの違いが大事なんですね。」
先輩
「そうだね。Thymeleafはサーバーサイドの変数展開、JavaScriptはクライアントサイドの動的処理。両者を正しく理解すれば、Springでの動的Web開発がぐっと楽になるよ。」