こんにちは、くまごろーです。
今日はちょっとイレギュラーなFormの使い方についてまとめます。
今まで作成したFormは「1つのFormで、1つのインスタンスの情報を送る」という形式のものだったのですが、(ログインフォームとか)
アプリを作っている中で、「1つのFormの中に、2つのインスタンスの情報が含まれている」Formが欲しいという状況になりました。
わかってしまえば簡単だったんですが、最初かなり調べまくったので、ここでまとめようと思います。
1 どういう状況か
今回はこんな感じの状況でした。
ユーザー設定変更のフォームなんですが、
下記の様な方法で処理したいと考えていました。
- アップロードした画像は、ファイル専用のインスタンスとして送りたい。
- それ以外の情報は、userインスタンスで送りたい。
2 Controllerクラス
結果的にすごいシンプルな方法でいけました。
@Transactional @PostMapping("/setting") public String process(@Validated @ModelAttribute("user") SiteUser user, BindingResult result, @ModelAttribute("file") FileUploadForm file, HttpServletResponse response, Authentication loginUser, RedirectAttributes redirectAttributes) { //処理内容は省略 }
かなり長ったらしいですが・・・
public String process(@Validated @ModelAttribute("user") SiteUser user, BindingResult result, @ModelAttribute("file") FileUploadForm file, ) {
上記のように、とりあえず@ModelAttributeアノテーションを付けて並置すればOKです。
3 viewクラス
↑に対するhtmlファイルがこれ。
<form enctype="multipart/form-data" th:action="@{/setting}" method="post" novalidate> <div class="file-field input-field"> <div class="btn"> <span>アイコン画像選択</span> <input type="file" th:field="${file.uploadedFile}"></div> <div class="file-path-wrapper"> <input class="file-path validate" type="text" th:field="${user.icon}"></div></div> <input type="hidden" name="username" th:value="${user.username}" /> <input type="hidden" name="createdAt" th:value="${user.createdAt}" /> <input type="hidden" name="role" th:value="${user.role}" /> <input type="hidden" name="password" th:value="${user.password}" /> <div class="form-group"> <label for="name">ユーザー名(2文字以上20文字以内) </label> <input type="text"th:errorclass="is-invalid" th:field="${user.userNickname}"> <div class="invalid-feedback" th:errors="${user.userNickname}"></div> </div> <!-- 略 --> <button class="btn setting-update">更新</button> </form>
本当にくだらない話なんですが、私Formで情報を送信するときは、必ずformタグに
th:object="${user}"
みたいに、特定のインスタンスを指定しなきゃいけないと思ってたんですよ(=_=;)
だから、「1つのフォームで複数のインスタンスの情報送るのは無理じゃない?」と思ってたんですが・・・
何はともあれ、うまくいってよかったです。
4 参考