Thymeleaf javascript inlineの書き方と使い方を完全ガイド!初心者でもわかるテンプレートエンジンとJavaScript連携
新人
「先輩、ThymeleafでJavaScriptと連携する方法を調べていたんですが、th:inline="javascript"ってどう使うんですか?」
先輩
「お、いいところに気づいたね。Thymeleafのth:inlineは、JavaScriptの中でサーバー側の変数を埋め込むための機能なんだよ。」
新人
「なるほど!でも、どうやって値を渡すのかいまいちピンときません…。」
先輩
「じゃあ、ThymeleafとJavaScriptの基本的な仕組みから順に見ていこうか。」
1. Thymeleafとは?(テンプレートエンジンの基本)
Thymeleaf(タイムリーフ)は、Spring Frameworkでよく使われるテンプレートエンジンです。HTMLファイルの中にJavaの変数やデータを埋め込むことができ、動的にWebページを生成できます。特に、@Controllerで渡した値を簡単にHTML上で表示できるのが魅力です。
たとえば、Spring Bootプロジェクトでコントローラから「メッセージ」を渡して、それをHTMLに表示したいときに、Thymeleafを使えばとてもシンプルに書けます。
@Controller
public class SampleController {
@GetMapping("/hello")
public String showPage(Model model) {
model.addAttribute("message", "こんにちは、Thymeleafの世界へ!");
return "hello";
}
}
上記のように、Modelに属性を追加すると、HTML側で${message}として参照できます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello Page</title>
</head>
<body>
<p th:text="${message}">ここにメッセージが表示されます</p>
</body>
</html>
このようにThymeleafは、HTMLをテンプレートとして使いながらJavaのデータを埋め込むことができるテンプレートエンジンなのです。
2. JavaScriptとThymeleafを連携する目的
ThymeleafとJavaScriptを連携する目的は、サーバー側の値をクライアント側(JavaScript)で利用するためです。例えば、ログイン中のユーザー名や商品リストなどをサーバーから受け取り、JavaScriptで画面に動的表示したい場合があります。
通常、HTMLのth:textで値を埋め込むことはできますが、JavaScriptの中に直接変数として組み込みたい場合は、th:inline="javascript"を使います。これにより、サーバーから渡された値をスクリプトの中で安全に扱えるようになります。
例えば、次のようにJavaScript内でサーバー変数を展開できます。
<script th:inline="javascript">
let message = [[${message}]];
console.log(message);
</script>
これにより、サーバーで設定した「message」の値が、JavaScriptの変数messageとして展開され、ブラウザのコンソールで確認できるようになります。
3. th:inline="javascript"とは何か(役割と基本構文)
th:inline="javascript"は、Thymeleafのテンプレート内でJavaScriptを扱うための特別な設定です。この指定をすると、[[${...}]]のような構文が使えるようになり、サーバー側の値をJavaScriptの変数やオブジェクトに直接展開できます。
これを使わないと、JavaScript内での変数展開がうまく機能しません。通常のHTML埋め込みと違って、th:inlineはスクリプトタグの中で動的な処理を行う仕組みを持っています。
実際の使い方は以下のようになります。
<script th:inline="javascript">
let userName = [[${userName}]];
let items = [[${itemList}]];
</script>
この例では、サーバー側で設定されたuserNameとitemListの値を、JavaScriptの変数として利用できます。
例えばコントローラ側で以下のように値を渡していたとします。
@Controller
public class InlineController {
@GetMapping("/inline")
public String inline(Model model) {
model.addAttribute("userName", "田中太郎");
model.addAttribute("itemList", List.of("ノートPC", "マウス", "キーボード"));
return "inline-sample";
}
}
このとき、HTML側では以下のようにJavaScriptの変数に埋め込みができます。
<script th:inline="javascript">
let user = [[${userName}]];
let list = [[${itemList}]];
console.log(user);
console.log(list);
</script>
ブラウザのコンソールで確認すると、サーバーから渡された値が正しく展開されているのが分かります。
田中太郎
["ノートPC", "マウス", "キーボード"]
このように、th:inline="javascript"を使うことで、サーバーサイド(Java)とクライアントサイド(JavaScript)を自然に連携させることができます。特に、フォームの動的表示やグラフ描画などに活用できるため、Spring開発では欠かせないテクニックのひとつです。
4. 基本的なth:inline="javascript"の書き方
ここからは、Thymeleafのth:inline="javascript"を使った具体的な書き方を詳しく見ていきましょう。この構文を理解すれば、サーバーから渡された値をJavaScript内で自由に使えるようになります。特に、動的に表示を切り替えたい場面や、サーバーから受け取ったデータをグラフやリストに反映したい場面でとても役立ちます。
まず、最も基本的な記述方法は次の通りです。
<script th:inline="javascript">
let message = [[${message}]];
</script>
このように書くと、サーバーでModelに設定したmessageの値が、JavaScriptの変数messageに展開されます。ここで大切なのは、二重角かっこ([[ ]])を使うことです。これはThymeleafのJavaScriptモード専用の構文で、通常のHTMLタグで使う${}とは異なります。
もしth:inlineを指定せずに同じコードを書いた場合、ただの文字列として扱われてしまいます。つまり、サーバーの値はJavaScriptに正しく埋め込まれません。th:inline="javascript"を指定することで、Thymeleafがスクリプト内の変数展開を有効にし、サーバーの値を正しい形式で出力してくれるのです。
また、JavaScript内で安全に文字列を扱うため、Thymeleafは自動的にエスケープ処理を行ってくれます。これにより、特殊文字や改行を含むデータも安心して扱うことができます。
5. コントローラから値を渡してJavaScriptで使う方法
次に、実際にSpringの@Controllerから値を渡し、それをJavaScript内で利用する流れを確認してみましょう。ここでは、pleiades環境でGradleプロジェクトを作成し、コントローラからユーザー情報を渡す例を紹介します。
@Controller
public class UserController {
@GetMapping("/user-info")
public String showUser(Model model) {
model.addAttribute("userName", "山田花子");
model.addAttribute("userAge", 28);
return "user-info";
}
}
このコントローラでは、userNameとuserAgeの2つのデータをビューに渡しています。HTML側では、これをJavaScript内で次のように受け取ります。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ユーザー情報</title>
</head>
<body>
<h3>ユーザー情報ページ</h3>
<script th:inline="javascript">
let name = [[${userName}]];
let age = [[${userAge}]];
console.log("ユーザー名:" + name);
console.log("年齢:" + age);
</script>
</body>
</html>
このように書くと、サーバーで設定したuserNameとuserAgeがブラウザのJavaScript変数に展開されます。実際にページを開いてブラウザのコンソールを確認すると、次のような出力が表示されます。
ユーザー名:山田花子
年齢:28
この仕組みを使えば、サーバーサイドのデータをJavaScriptで動的に利用できるようになります。たとえば、画面上にユーザー情報を表示したり、JavaScriptで条件分岐を行ってページのレイアウトを変えることも可能です。
また、注意すべき点として、数値やオブジェクトを扱う際は型に注意することが大切です。Thymeleafは自動でJavaScriptのデータ型に変換してくれますが、文字列として扱いたい場合はシングルクォートを明示的に付けて制御するとよいでしょう。
6. 文字列・数値・配列・オブジェクトの埋め込み例
ここでは、Thymeleafのth:inline="javascript"を使って、文字列・数値・配列・オブジェクトといったさまざまなデータをJavaScriptに埋め込む方法を解説します。これらを理解すれば、どんな種類のデータでもスムーズに扱えるようになります。
まずは文字列と数値の基本的な例です。
@Controller
public class DataController {
@GetMapping("/data")
public String data(Model model) {
model.addAttribute("userName", "佐藤一郎");
model.addAttribute("userScore", 95);
return "data-sample";
}
}
<script th:inline="javascript">
let name = [[${userName}]];
let score = [[${userScore}]];
console.log(name);
console.log(score);
</script>
文字列はダブルクォートで囲まれて自動的に安全な形式で出力され、数値はそのまま数値型として展開されます。ブラウザのコンソールで確認すると、次のような結果になります。
佐藤一郎
95
次に、配列を扱う例です。リストや配列をサーバーから渡すと、JavaScriptでは自動的に配列形式に変換されます。
@Controller
public class ListController {
@GetMapping("/list")
public String showList(Model model) {
model.addAttribute("items", List.of("りんご", "みかん", "ぶどう"));
return "list-sample";
}
}
<script th:inline="javascript">
let fruits = [[${items}]];
console.log(fruits);
</script>
["りんご", "みかん", "ぶどう"]
このように、配列データも簡単にJavaScriptへ渡せます。フォームの選択肢やグラフ表示など、動的にリストを扱う場面で便利です。
最後に、オブジェクト(Map)を渡す例です。ThymeleafはMap<String, Object>をJavaScriptのオブジェクトリテラルに変換してくれます。
@Controller
public class MapController {
@GetMapping("/map")
public String showMap(Model model) {
Map<String, Object> user = new HashMap<>();
user.put("name", "高橋涼");
user.put("age", 32);
user.put("email", "takahashi@example.com");
model.addAttribute("userInfo", user);
return "map-sample";
}
}
<script th:inline="javascript">
let user = [[${userInfo}]];
console.log(user.name);
console.log(user.age);
console.log(user.email);
</script>
高橋涼
32
takahashi@example.com
このように、文字列・数値・配列・オブジェクトのすべてに対応しており、サーバーのデータをJavaScriptで直感的に扱えるのがThymeleafの強みです。特に、複数のデータをまとめて画面に表示したい場合や、非同期処理に渡すパラメータとして使いたいときに非常に便利です。
さらに、th:inline="javascript"を使うと、データが自動的に適切な形式に整形されるため、エスケープ処理を意識せずに安全なコードを書くことができます。これにより、テンプレート内でJavaScriptの記述がすっきりし、メンテナンス性も向上します。
7. 実践例:Thymeleafで生成したデータをJavaScriptで動的表示する
ここでは、ThymeleafとJavaScriptの連携をより実践的に体験してみましょう。実際にサーバーから渡したデータをJavaScriptで受け取り、画面上に動的に表示するサンプルを作成します。Springの@Controller構成でデータを渡し、Thymeleafのth:inline="javascript"を使って値をスクリプト内に展開します。
まず、コントローラ側のコードです。今回は、商品リストをサーバーから渡して画面上に一覧表示する例を扱います。
@Controller
public class ProductController {
@GetMapping("/products")
public String showProducts(Model model) {
List<Map<String, Object>> productList = new ArrayList<>();
productList.add(Map.of("name", "ノートパソコン", "price", 120000));
productList.add(Map.of("name", "マウス", "price", 2500));
productList.add(Map.of("name", "キーボード", "price", 4800));
model.addAttribute("products", productList);
return "product-list";
}
}
このコントローラでは、商品名と価格の情報を持つリストを作成し、モデルに登録しています。Thymeleafのテンプレート側では、このproductsをJavaScriptに展開して、HTML上で商品一覧を生成します。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>商品リスト</title>
</head>
<body>
<h3>商品一覧</h3>
<ul id="product-list"></ul>
<script th:inline="javascript">
let items = [[${products}]];
let ul = document.getElementById("product-list");
items.forEach(function(item){
let li = document.createElement("li");
li.textContent = item.name + ":" + item.price + "円";
ul.appendChild(li);
});
</script>
</body>
</html>
ページを開くと、サーバーで渡した商品データがJavaScriptを通じてリスト表示されます。このように、ThymeleafとJavaScriptを組み合わせることでサーバーからのデータを動的にレンダリングできるのです。もしこの処理を通常のth:eachで書くと、サーバー側でHTMLを生成してしまいますが、th:inline="javascript"を使えば、クライアント側のJavaScriptで制御が可能になります。
この方法は、リアルタイムで更新したいデータや、Ajax通信で描画内容を再構築したい場面にも応用できます。
8. よくあるエラー(undefined・展開されない)とその原因
Thymeleafのth:inline="javascript"を使うとき、初心者が最もつまずきやすいのが「値がundefinedになる」「変数が展開されない」といったエラーです。これらの問題は、いくつかの典型的な原因に分けられます。
(1)th:inlineを指定していない
スクリプトタグにth:inline="javascript"を付け忘れると、Thymeleafはスクリプト内の[[${...}]]構文を認識しません。その結果、JavaScript側ではただの文字列のまま扱われ、undefinedや文字列リテラルのままになることがあります。
(2)変数名のミスやModel未設定
コントローラで設定した属性名と、HTMLで参照している名前が一致していない場合も値が展開されません。model.addAttribute("userName", "山田")としたなら、HTMLでは必ず[[${userName}]]と書く必要があります。
(3)スクリプトの読み込み順
スクリプトをHTMLの上部に記述している場合、DOM要素がまだ生成されておらず、JavaScriptで参照できないことがあります。そのため、th:inline="javascript"のスクリプトは</body>直前に記述するのが安全です。
(4)文字列のエスケープ問題
ThymeleafはJavaScript出力時に自動でエスケープ処理を行いますが、場合によっては改行や特殊文字が原因で不正なJSON形式になることがあります。特に日本語や引用符を含む文字列を扱う際は、値を一度JSON.stringify()で確認するのもおすすめです。
これらのエラーを防ぐためには、まずth:inline="javascript"を正しく設定し、Modelのキーとテンプレートの変数名を統一すること、さらにスクリプトの位置を見直すことが重要です。初心者の多くは「書き方は合っているのに値が出ない」と感じますが、実際にはこうした基本設定の抜けが原因であることがほとんどです。
9. 効果的な使い方と開発のコツ(安全な値の埋め込み・コメント構文)
最後に、ThymeleafとJavaScriptをより安全かつ効果的に使うためのポイントを紹介します。特にth:inline="javascript"を用いたデータ埋め込みでは、セキュリティや可読性を意識した設計が重要です。
(1)安全な値の埋め込み
Thymeleafは自動でエスケープ処理を行うため、基本的にはXSS攻撃などのリスクを低減できます。しかし、外部入力をそのままJavaScript変数に埋め込むのは避けましょう。必要に応じてth:utextではなくth:textを使用し、サーバー側で検証済みの値だけを埋め込むのが基本です。
(2)コメント構文の活用
Thymeleafでは、JavaScript内にコメントを残す場合も/*[[...]]*/のように書くことで、テンプレート内の値をコメント化できます。例えば次のように使います。
<script th:inline="javascript">
/*[[${userInfo}]]*/
</script>
この形式で記述すると、サーバー側では実際に値が展開されず、開発中の確認用コメントとして活用できます。Thymeleafのテンプレート構文がHTMLバリデータでエラーにならないようにしたいときにも有効です。
(3)デバッグ時のコツ
値が正しく展開されているか確認するには、まずブラウザのコンソールを活用します。console.log()を使って展開結果を出力すれば、サーバー側のModelの値が意図通りにJavaScriptへ渡っているかが分かります。また、開発中はThymeleafのキャッシュ機能を無効化しておくと、テンプレートを修正した内容が即時反映されるため便利です。
(4)複雑なデータ構造の扱い
リストやマップがネストされた複雑な構造になると、JavaScript側では階層的にアクセスする必要があります。例えば、[[${user.profile.name}]]のようにドット表記を使うと、オブジェクト内のプロパティを安全に取得できます。Thymeleafは内部で自動的にnullチェックを行うため、存在しないキーを参照しても致命的なエラーにはなりません。
(5)テンプレート設計のポイント
JavaScriptへの埋め込みは便利ですが、ロジックを過剰にテンプレート側に寄せすぎないことも重要です。サーバー側ではデータの整形や検証を完了させ、テンプレートでは「最小限の動的生成」にとどめる方が、可読性や保守性が高まります。
このように、Thymeleafのth:inline="javascript"は単なるデータ展開の仕組みではなく、安全かつ効率的にJavaとJavaScriptを連携させるための強力な機能です。適切に使えば、サーバーからのデータを動的に扱いながらもセキュリティを維持できる美しいテンプレート設計が可能になります。初心者のうちは単純な値渡しから始め、徐々に配列やオブジェクトを扱う練習を重ねることで、確実にThymeleafの力を引き出せるようになるでしょう。
まとめ
今回の記事では、Spring Boot開発において非常に重要な役割を果たすThymeleaf(タイムリーフ)とJavaScriptの連携について詳しく解説してきました。特に、サーバー側で保持しているJavaのデータをフロントエンドのスクリプト側で活用するためのth:inline="javascript"の使い方は、動的なWebアプリケーションを構築する上で避けては通れない必須テクニックです。
Thymeleaf JavaScript連携の要点
改めて重要なポイントを整理すると、以下の3点に集約されます。
- th:inline="javascript"の宣言: これを
<script>タグに記述することで、Thymeleaf独自のインライン構文が有効になります。 - 二重角かっこ [[${...}]]: JavaScript内で変数を展開する際は、通常のHTML属性で使う形式ではなく、この専用構文を使用します。
- 自動エスケープと型変換: 文字列は自動的にクォートで囲まれ、数値や配列、Map(オブジェクト)もJavaScriptが理解できる形式に自動変換されるため、開発者は型を過度に意識せずに済みます。
実践的なサンプルプログラム
まとめとして、学んだ内容を凝縮したサンプルプログラムを掲載します。コントローラから「ユーザーの状態」と「設定値」を渡し、JavaScript側でそれに応じた処理を行うコードです。
// コントローラ側:Javaでデータを準備
@Controller
public class SummaryController {
@GetMapping("/summary")
public String summaryPage(Model model) {
// 文字列の受け渡し
model.addAttribute("status", "success");
// 数値の受け渡し
model.addAttribute("retryCount", 3);
// Map(オブジェクト)の受け渡し
Map<String, Object> config = new HashMap<>();
config.put("theme", "dark");
config.put("language", "ja");
model.addAttribute("userConfig", config);
return "summary-view";
}
}
<!-- ビュー側(HTML):JavaScriptへ値を注入 -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Thymeleafインラインまとめ</title>
</head>
<body>
<h1>連携処理の動作確認</h1>
<script th:inline="javascript">
// 1. 基本的な値の取得
const status = [[${status}]];
const retries = [[${retryCount}]];
// 2. オブジェクトとして受け取る
const config = [[${userConfig}]];
// 3. 取得した値を使ったロジック
console.log("現在のステータス:", status);
console.log("設定されたテーマ:", config.theme);
if (status === "success") {
alert(config.language === "ja" ? "読み込みに成功しました!" : "Load Successful!");
}
</script>
</body>
</html>
このように、サーバーサイドのロジックとクライアントサイドの動作をシームレスに繋ぐことができるのがThymeleafの魅力です。最初は「[[...]]」という独特な書き方に戸惑うかもしれませんが、一度慣れてしまえば、これほど便利なテンプレートエンジンはありません。ぜひ、日々の開発の中で積極的に活用し、ユーザーにとって使い勝手の良い、動的でリッチなWebサイトを構築してみてください。
生徒
「先生、今回のまとめでth:inline="javascript"の使い方がかなり明確になりました!特に、JavaのMapがそのままJavaScriptのオブジェクトとして使えるのが本当に便利ですね。」
先生
「そうだね。昔は一度隠しフィールド(input type="hidden")に値を書き出して、それをJavaScriptで取得する……なんて手間をかけていたけれど、Thymeleafなら直接スクリプト内に変数を注入できるから、コードがすごくスッキリするんだよ。」
生徒
「確かに!でも、もし[[${...}]]を書き間違えて、コントローラに存在しない名前を指定しちゃったらどうなるんですか?」
先生
「いい質問だね。その場合は、JavaScript側でnullとして扱われることが多いよ。ブラウザのコンソールでundefinedやエラーが出たときは、まずコントローラのModelにセットしたキー名と、HTML側の綴りが合っているか確認するのがデバッグの鉄則だね。」
生徒
「なるほど、綴りミスは要注意ですね。あと、セキュリティについても自動でエスケープしてくれると聞いて安心しました。これで自信を持ってJavaからJavaScriptへデータを渡せそうです!」
先生
「その意気だよ。ただ、あまりに大量のデータをJavaScriptに流し込みすぎるとページの読み込みが重くなることもあるから、必要なデータだけを厳選して渡すのが、プロのエンジニアへの第一歩だね。頑張って!」