Thymeleafのフォームバインディング、困っていませんか?
Spring BootでWebアプリを作っていると、必ず直面するのが「フォーム入力をオブジェクトにバインドする方法」です。
「input要素に何を設定すれば値が入るの?」 「バリデーションエラー時に、値が消えてしまう…」 「th:fieldってよく見るけど、どう動いているの?」
そんな疑問を持ったことはありませんか?この記事では、Thymeleafのフォームバインディングに欠かせない「th:object」の使い方を、初心者にもわかりやすく丁寧に解説します。
th:objectの基本と実践
th:objectとは?
th:objectは、フォーム全体にバインドするモデルオブジェクトを指定するための属性です。これを使うと、フォーム内の各フィールドに自動的にオブジェクトのプロパティがマッピングされます。
実は、th:objectは<form>タグに限らず、<main>や<div>などの任意の親要素にも指定することができます。たとえば、以下のようにしておけば、フォーム以外の複数の要素から同じオブジェクトを参照することが可能です。
<main th:object="${user}">
<form method="post">
<input type="text" th:field="*{name}" />
<input type="email" th:field="*{email}" />
</form>
</main>
このように、上位の要素にth:objectを設定することで、ネストされたフォームや入力エリアでも一貫して同じオブジェクトをバインドできる柔軟な設計が可能になります。
◾️基本構文
<form th:object="${user}" method="post">
<input type="text" th:field="*{name}" />
<input type="email" th:field="*{email}" />
<button type="submit">送信</button>
</form>
このように、th:objectに${user}を指定すると、userオブジェクトのnameやemailプロパティがそれぞれのフォームフィールドとバインドされます。
これは宛名(th:object)を封筒に書くことで、中に入れる手紙(th:field)がどこへ届くか明確になるようなものです。宛名がなければ、手紙が誰宛か分からず混乱してしまいますよね。th:objectはフォーム全体の「宛名」を指定することで、個々のth:fieldが正しくプロパティとつながるようにしてくれるのです。
◾️Java側のクラス
public class User {
private String name;
private String email;
// getterとsetterは省略
}
◾️コントローラー例
@GetMapping("/form")
public String showForm(Model model) {
model.addAttribute("user", new User());
return "form";
}
@PostMapping("/form")
public String submitForm(@ModelAttribute User user, Model model) {
// バリデーションや保存処理など
model.addAttribute("user", user);
return "result";
}
th:fieldと組み合わせる意味
th:field=”*{プロパティ名}”という記法は、th:objectで指定されたオブジェクトを参照してくれます。*{}という構文がポイントです。
-
th:object:バインドするモデルオブジェクトを指定します。
-
th:field:指定されたオブジェクトのプロパティと自動的に連携します。
よくあるつまずきポイントと改善例
【つまずき①】th:objectが指定されていない
<!-- NG例 -->
<form method="post">
<input type="text" th:field="*{name}" />
</form>
これはth:objectが指定されていないため、*{}の参照先がわからずエラーになります。
◾️修正例
<form th:object="${user}" method="post">
<input type="text" th:field="*{name}" />
</form>
【つまずき②】エラーメッセージの表示ができない
バリデーションエラー時のメッセージ表示には、SpringのBindingResultとThymeleafのエラー表示を組み合わせる必要があります。
◾️Java側
@PostMapping("/form")
public String submitForm(@Valid @ModelAttribute User user, BindingResult result, Model model) {
if (result.hasErrors()) {
return "form";
}
return "result";
}
◾️HTML側
<div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>
【before / afterの改善例】
Before:
<form method="post">
<input type="text" name="name" />
</form>
After:
<form th:object="${user}" method="post">
<input type="text" th:field="*{name}" />
</form>
Thymeleafの機能を使うことで、バリデーションや初期値の自動反映が簡単に行えるようになります。
th:objectを使いこなして、堅牢なフォーム開発を!
th:objectは、フォームとオブジェクトを連携させる要の機能です。
-
モデルオブジェクトとのマッピングが簡単になる
-
バリデーションやエラー表示もスムーズに実装できる
-
コードの可読性・保守性が向上する
実務でThymeleafを使うなら、必ず習得しておきたいポイントです。
【外部リンク】
Spring Framework公式ガイド – Spring MVC
Spring公式ドキュメント:@ModelAttributeの使い方