Thymeleaf(+ Spring MVC) におけるフォーム

各フォーム部品におけるThymeleafのタグの使い方。th:fieldが中心だが部品の特性によって差はあるのでメモ。

各フォーム部品におけるThymeleafのタグの使い方。th:fieldが中心だが部品の特性によって差はあるのでメモ。

概要

Spirng MVCとThymeleafでフォームを生成する場合は「th:field」を中心に考える。「th:field」を指定すればidやname属性などを生成や、戻る遷移時のvalue設定なども行ってくれる。

ファイル選択フォームについては次のページを参照。→こちら

サンプルについて

サーバー側では次のようにフォームやenumを設定する。

例で使用するフォーム
@Data
public class SimpleInputForm {
  String name;
  String[] favariteMovies;
  String fisrtMovie;
  String secondMovie;
}
例で使用するenum
@AllArgsConstructor
@Getter
public enum Movie {

  スターウォーズ("star-wars", "スターウォーズ"),
  ローマの休日("roman-holiday", "ローマの休日"),
  トイストーリー("toy-story", "トイ・ストーリー");

  private final String code;
  private final String label;
}
enumはvalues()を使って渡す
model.addAttribute("movies", Movie.values());

フォームの生成

テキスト

th:fieldを指定すればid,name,valueの設定をしてくれる。

thymeleaf
<form method="post" action="#" th:action="@{./confirm}" th:object="${form}">
  <input type="text"  th:field="*{name}" />
</form>
生成されるhtml
<form method="post" action="./confirm">
  <input type="text" class="form-control" id="name" name="name" value="" />
</form>

チェックボックス

Listやenumから生成する場合でもth:fieldを使える。th:valueを設定しておけば、その値と一致している場合にchecked="checked"が付与される。valueがonのhiddenフィールドも生成されるが、これはチェックを外したときに値を送らない対策。

labelとidの生成については、#idsユーティリティが便利。labelの位置が前か後ろかによって「prev」「next」を使い分ける。

thymeleaf
<form method="post" action="#" th:action="@{./confirm}" th:object="${form}">
  <ul>
      <li th:each="movie : ${movies}">
         <input type="checkbox" th:field="*{favariteMovies}" th:value="${movie.code}" />
          <label th:for="${#ids.prev('favariteMovies')}" th:text="${movie.label}">映画名</label>
      </li>
  </ul>
</form>
生成されるhtml
<form method="post" action="./confirm">
  <ul>
     <li>
       <input type="checkbox" value="star-wars" id="favariteMovies1" name="favariteMovies" />
       <input type="hidden" name="_favariteMovies" value="on" />
       <label for="favariteMovies1">スターウォーズ</label>
     </li>
    <li>
      <input type="checkbox" value="roman-holiday" id="favariteMovies2" name="favariteMovies" />
      <input type="hidden" name="_favariteMovies" value="on" />
      <label for="favariteMovies2">ローマの休日</label>
    </li>
    <li>
      <input type="checkbox" value="toy-story" id="favariteMovies3" name="favariteMovies" />
      <input type="hidden" name="_favariteMovies" value="on" />
      <label for="favariteMovies3">トイ・ストーリー</label>
    </li>
  </ul>
</form>

ラジオ

考え方はチェックボックスと一緒。

thymeleaf
<form method="post" action="#" th:action="@{./confirm}" th:object="${form}">
  <ul>
    <li th:each="movie : ${movies}">
      <input type="radio" th:field="*{fisrtMovie}" th:value="${movie.code}" />
      <label th:for="${#ids.prev('fisrtMovie')}" th:text="${movie.label}">映画名</label>
   </li>
  </ul>
</form>
生成されるhtml
<form method="post" action="./confirm">
  <ul>
    <li>
      <input type="radio" value="star-wars" id="fisrtMovie1" name="fisrtMovie" />
      <label for="fisrtMovie1">スターウォーズ</label>
    </li>
    <li>
      <input type="radio" value="roman-holiday" id="fisrtMovie2" name="fisrtMovie" />
      <label for="fisrtMovie2">ローマの休日</label>
    </li>
    <li>
      <input type="radio" value="toy-story" id="fisrtMovie3" name="fisrtMovie" />
      <label for="fisrtMovie3">トイ・ストーリー</label>
    </li>
  </ul>
</form>

セレクト(ドロップダウン)

selectタグのth:fieldとoptionタグのth:valueが一致するとselectedを付与する。

thymeleaf
<form method="post" action="#" th:action="@{./confirm}" th:object="${form}">
  <select th:field="*{secondMovie}">
    <option th:each="movie : ${movies}" th:value="${movie.code}" th:text="${movie.label}">映画名</option>
  </select>
</form>
生成されるhtml
<form method="post" action="./confirm">
  <select id="secondMovie" name="secondMovie">
    <option value="star-wars">スターウォーズ</option>
    <option value="roman-holiday">ローマの休日</option>
    <option value="toy-story">トイ・ストーリー</option>
  </select>
</form>

Appendix A: 参考