Thymeleaf th:valueでフォーム値を埋め込む書き方
新人
「Springでフォームを使いたいんですけど、入力欄に初期値を入れるにはどうすればいいんですか?」
先輩
「それなら、Thymeleafのth:value属性を使うのが基本だよ。Controllerから渡した値をHTMLに埋め込むんだ。」
新人
「なるほど!でもth:valueってどうやって使うんですか?」
先輩
「じゃあ、Thymeleafのth属性とth:valueの基本を順番に見ていこうか。」
1. HTMLフォームにおける値の埋め込みとは?
Webアプリケーションでは、ユーザーがフォームに入力した値をサーバーに送信し、その値を再表示する場面がよくあります。たとえば、ユーザー情報の編集画面では、すでに登録されている名前やメールアドレスなどの値をフォームに表示する必要があります。
このとき、ただのHTMLだけではフォームに動的な値を埋め込むことができません。そこで登場するのがThymeleafです。
Thymeleafはテンプレートエンジンのひとつで、SpringアプリケーションにおいてHTMLとJavaのデータをつなぐ役割を果たします。
Thymeleafを使えば、HTMLタグの中にJavaの値を簡単に埋め込むことができます。
たとえば、以下のようにHTMLで書かれたinput要素に対して、Controllerから渡された値を表示させることができます。
<input type="text" th:value="${user.name}">
このようにして、入力欄にあらかじめ値を表示させることが可能になります。
2. Thymeleafのth属性とは何か?
ThymeleafではHTMLの属性を置き換えるために、th:で始まる独自の属性を使用します。これを「th属性」と呼びます。
HTMLの標準属性の代わりにth:属性名という形式を使うことで、Java側のデータをテンプレート内に埋め込むことができます。
たとえば、通常のHTMLでは以下のようにvalue属性を使います。
<input type="text" value="山田太郎">
しかし、これでは値が固定されており、Javaの変数を反映させることはできません。
そこでThymeleafでは、以下のようにth:valueを使います。
<input type="text" th:value="${user.name}">
このように書くと、ControllerでModelに設定されたuser.nameの値が、HTMLのinput要素に表示されるようになります。
ここで重要なのは、th:value属性はHTMLのvalue属性に置き換えられるという点です。
ブラウザで表示される最終的なHTMLは以下のようになります。
<input type="text" value="山田太郎">
つまり、th:valueは「テンプレート処理時にvalue属性へと変換される」という仕組みになっているのです。
また、動的なデータを扱うためには、SpringのControllerであらかじめオブジェクトをModelに追加しておく必要があります。
以下のように@Controllerクラス内でModelにデータを設定します。
@Controller
public class SampleController {
@GetMapping("/form")
public String showForm(Model model) {
User user = new User();
user.setName("山田太郎");
model.addAttribute("user", user);
return "form";
}
}
このように設定しておけば、テンプレートファイル内で${user.name}として値を参照することができます。
なお、開発環境はpleiadesを使用して、依存関係はGradleで管理されている前提です。プロジェクト作成時には、pleiadesの機能でSpring Bootの依存関係をチェックしておくことで、簡単にThymeleafも利用できます。
3. コントローラから渡した値をフォームに埋め込む方法(@Controller使用)
Springでは、@Controllerを使ってWebページに表示するデータをModelに追加することができます。フォームに初期値を表示したい場合は、あらかじめオブジェクトに値をセットしてModelに渡しておくことで、Thymeleafのth:valueでその値をHTMLに埋め込むことができます。
次の例では、ユーザー情報を扱うUserクラスのインスタンスに名前を設定し、それをModelに追加しています。
@Controller
public class UserController {
@GetMapping("/edit")
public String showForm(Model model) {
User user = new User();
user.setName("田中一郎");
model.addAttribute("user", user);
return "edit-form";
}
}
このようにmodel.addAttribute("user", user);とすることで、テンプレート内で${user.name}という形式で値を参照できるようになります。あとは、テンプレートでth:valueを使ってフォームのinput要素に値を表示させるだけです。
4. th:valueでフォームに値をバインドする具体的なコード例
実際にフォームで値をバインドするHTMLのコードは次のようになります。テンプレートファイル(例:edit-form.html)に以下のように記述します。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ユーザー情報編集</title>
</head>
<body>
<form action="#" th:action="@{/edit}" method="post">
<label>名前:</label>
<input type="text" name="name" th:value="${user.name}">
<button type="submit">送信</button>
</form>
</body>
</html>
この例では、input要素にth:value="${user.name}"と書くことで、Controllerで設定したユーザー名「田中一郎」が自動的にフォームに表示されます。これは、ユーザーがフォームを編集するときや、登録済みの情報を表示したいときにとても便利です。
Thymeleafのth:valueは、HTMLのvalue属性と連動しており、テンプレートエンジンによって最終的なHTMLに変換されます。HTMLソースをブラウザで確認すると、以下のように表示されます。
<input type="text" name="name" value="田中一郎">
このように、th:valueを使えば、JavaのオブジェクトのプロパティをHTMLフォームに自然に埋め込むことができるのです。
5. name属性とth:value属性の関係性とフォーム送信時の動作の流れ
ここで一度、name属性とth:value属性の関係について整理しておきましょう。
name属性はサーバーへ送信するためのキーです。フォームの入力値は、このname属性をキーとしてサーバーに渡されます。
一方、th:value属性はvalue属性に置き換えられて、フォーム表示時の初期値として表示される役割を持ちます。
この2つは役割が異なりますが、どちらもフォーム処理において欠かせない重要な要素です。
具体的な流れは以下のようになります。
- Controllerで
Modelにデータ(例:Userオブジェクト)を追加する - テンプレートHTML内で
th:valueを使ってそのデータをinput要素に表示する - フォームが送信されると、
name属性に指定された名前をキーとして、フォームの値がサーバーに送られる
以下は、送信された値を受け取るControllerの例です。
@Controller
public class UserController {
@PostMapping("/edit")
public String updateUser(@RequestParam String name, Model model) {
// nameの値を受け取って処理する
model.addAttribute("message", "更新された名前:" + name);
return "edit-result";
}
}
このようにして、フォームに入力された名前が@RequestParamで受け取られ、次の画面に表示されるといった処理が行われます。
なお、より高度なバインディングを行いたい場合は、@ModelAttributeを使ってオブジェクト全体をフォームと結びつけることも可能ですが、今回は基本的なth:valueの理解を深めることを優先しました。
このように、ControllerからModelへ値を渡し、それをテンプレートで表示し、さらにサーバーに戻すという一連の流れは、Spring MVCとThymeleafの基礎的な使い方として非常に重要です。
6. th:valueを使うときによくあるミスや落とし穴(null、初期値が入らないなど)
Thymeleafのth:valueを使ってフォームに値を埋め込むとき、初心者がよくつまずくポイントがあります。特に多いのが「値が表示されない」「nullがそのまま表示される」といった問題です。
たとえば、ControllerでModelに設定するオブジェクトがnullだった場合、以下のように書いても何も表示されなかったり、null文字列がそのまま表示されることがあります。
<input type="text" th:value="${user.name}">
このときの対策としては、ControllerでnullチェックをしてからModelに追加することが大切です。必要であれば、デフォルト値を設定しておきましょう。
User user = new User();
user.setName("未設定");
model.addAttribute("user", user);
また、Thymeleafの式中で安全にnullを扱いたい場合は、?:演算子(Elvis演算子)を使うと便利です。
<input type="text" th:value="${user.name ?: '未入力'}">
これにより、user.nameがnullだった場合に「未入力」という初期値を表示できます。フォームを扱うときは、こうしたnull対応を意識しておくと、表示ミスを防ぐことができます。
7. th:valueとth:fieldの違い
Thymeleafにはth:valueだけでなく、th:fieldという属性も存在します。どちらもフォームの値に関係しますが、用途や動作に違いがあります。
th:valueは「表示用」で、単にControllerから渡された値をフォームのvalue属性に出力するだけです。
一方、th:fieldは「バインディング用」で、Springのフォームオブジェクトとの連携を自動で行ってくれます。
以下に、両者の違いを簡単に比較します。
th:value→ 表示用。自分でname属性を指定する必要あり。th:field→ SpringのFormオブジェクトと連動。name属性などを自動生成。
初心者向けには、まずth:valueを使って動的に値を表示する仕組みを理解し、その後th:fieldを学ぶのがおすすめです。Springのバリデーションやエラーメッセージ表示と連携させたい場合は、th:fieldを使う場面が増えてきます。
8. 実務で使う際のポイントやTips(バリデーションやフォーム更新時の注意など)
実務でThymeleafのth:valueを使う際には、いくつか注意すべきポイントがあります。
まず、ユーザーが入力した値を再表示する場面では、バリデーションエラー後の再描画が重要になります。たとえば、Springのバリデーションでエラーが発生したとき、フォームに入力された内容がクリアされてしまうと、ユーザーの体験が悪くなります。
このような場合は、再描画時にも入力値が保持されるようにControllerでModelに値を再設定する、または@ModelAttributeを使ってオブジェクト全体をフォームにバインドすることで解決できます。
また、実務ではユーザーが入力した内容をそのままフォームに表示する場面が多いため、XSS(クロスサイトスクリプティング)対策にも気を配る必要があります。Thymeleafでは自動でエスケープされますが、th:utextなどを使う場合は注意が必要です。
さらに、フォーム更新処理では、hidden項目でIDを渡すケースも多いです。
<input type="hidden" name="id" th:value="${user.id}">
こうしておけば、どのユーザーの情報を更新するかをサーバー側で特定できます。
実務では細かい注意点もありますが、まずはth:valueを使って動的なデータ表示の基本を押さえておくことが重要です。
最初のうちはうまく値が表示されなかったり、nullエラーに悩まされることもあるかもしれませんが、少しずつ慣れていけば自然に使えるようになります。焦らず、一つひとつの仕組みを理解していきましょう。
まとめ
今回は、Thymeleafの中でも特に使用頻度が高いth:valueについて、入力フォームに動的な値を埋め込む方法を中心に振り返りました。フォームに初期値を設定することは、ユーザー編集画面や確認画面など、多くのWebアプリケーションで欠かせない要素です。入力フォームに値が表示されることで、ユーザーは現在保存されている情報を確認しつつ、必要な箇所だけを修正できます。また、SpringのControllerからModelへデータを設定し、Thymeleaf側で動的に埋め込むという仕組みを理解することで、フォーム処理がより滑らかで自然な実装になります。 HTMLだけでは変化する値を扱うことが難しい場面でも、Thymeleafのth属性を利用することで、動的な画面表示を柔軟に実現できます。今回の内容で特に重要なのは、「th:valueは最終的にvalue属性に変換される」という基本的な仕組みを正しく押さえることです。これにより、テンプレートエンジンとしてのThymeleafがどのようにHTMLとJavaの値をつないでいるのかが理解しやすくなります。 また、入力フォームが多い画面では、th:valueの役割が特に大きく、ユーザーの利便性を大きく左右します。ユーザーが何度も同じ情報を入力する手間を避けるためにも、初期値を表示する技術は非常に価値があります。例えば、ユーザー名・メールアドレス・プロフィール情報の編集など、一般的なアプリケーションの多くで活用される場面が多く、実務でも頻繁に登場します。 以下に、記事内容の復習として、今回のテーマに沿ったサンプルコードをまとめています。
Thymeleafでフォームに動的値を埋め込むサンプルコード
<form th:action="@{/update}" method="post" class="card p-3">
<label class="fw-bold mb-1">お名前</label>
<input type="text" th:value="${user.name}" class="form-control mb-3" />
<label class="fw-bold mb-1">メールアドレス</label>
<input type="email" th:value="${user.email}" class="form-control mb-3" />
<label class="fw-bold mb-1">コメント</label>
<textarea th:value="${user.comment}" class="form-control mb-3"></textarea>
<button class="btn btn-primary">更新する</button>
</form>
このサンプルでは、Controllerで渡されたオブジェクトのプロパティを、Thymeleafのth:valueを利用してフォームへ自然に反映しています。フォームの入力欄が多くなるほど、th:valueはより重要な役割を果たします。値をバインドしておくことで、フォーム送信時のエラーが発生しても、入力値を保持したまま画面を再描画できるため、ユーザー体験の向上にもつながります。 さらに、SpringのModelに値を追加してテンプレートへ渡すという流れを理解することで、バックエンドからフロントエンドまでのデータの流れがひとつにつながり、アプリケーション全体を見通しよく把握できるようになります。今回の内容は、後に学ぶフォームバリデーションやオブジェクトバインディングにも密接に関係するため、確実に押さえておくことが大切です。
生徒:「th:valueがどうして必要なのか、今日の解説でよく理解できました。入力値をそのまま表示できるのは本当に便利ですね。」
先生:「そうですね。特に編集画面では必須になりますし、ユーザーにとっても使いやすい画面を作るための基本になります。」
生徒:「ControllerでModelに値を追加して、それをテンプレートに表示する流れも自然で覚えやすかったです。」
先生:「SpringとThymeleafの組み合わせはとても直感的なんですよ。正しい仕組みを理解していくと、複雑なフォームでも作れるようになります。」
生徒:「バリデーションをかけたときに入力値が消えない仕組みも、th:valueのおかげなんですね。」
先生:「そのとおりです。ユーザーの操作性を高めるための重要なポイントですね。今日の内容を土台にして、次はフォームバインディングやエラーメッセージの表示なども学んでいきましょう。」
生徒:「はい!今回の知識をしっかり活かせるように練習していきます。」