概要
共通ヘッダーの「新規登録」リンクから遷移する、書籍情報登録画面を作成します。
遷移できるようにControllerの作成と、遷移先である画面をHTMLで作成していきます。
Formクラスの作成
登録画面の項目をViewとController間で受け渡すためのFormオブジェクトを作成します。
配置先:src > main > java > com > example > demo > controller > form > BookForm.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.example.demo.controller.form; import java.text.SimpleDateFormat; import java.util.Date; import lombok.Data; @Data public class BookForm { private int id; private String name; private String isbn; private String description; private String publisher; private Integer price; private Date publication_date; private int version; } |
・@Data
Lombokのアノテーションで、Getter/Setterを利用可能にしてくれる。
つまり、getId()や、setId(int id)などを書かなくても使えるようになります。
Controllerの作成
・BookController.javaを作成します。
配置先:src > main > java > com > example > demo > controller > BookController.java
・コードを以下のように記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.example.demo.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import com.example.demo.controller.form.BookForm; @Controller public class BookContorller { @GetMapping("book/add") public String getAdd(BookForm form, Model model) { model.addAttribute("bookForm", form); return "book/add"; } } |
・@Controller
クラスをControllerとして認識するようにするアノテーションです。
Controllerとしたいクラスに指定します。
・@GetMapping(“book/add”)
リクエストを受け取る指定を行っています。
@GetMappingでGetメソッドであること、
(“book/add”)でドメイン以下のURLが「book/add」であることを定義しています。
・model.addAttribute(“bookForm”, form);
遷移するViewの「bookForm」に「form」オブジェクトを渡します。
・return “book/add”;
遷移する画面を指定します。
ここでは「book/add」としているので、以下を指定していることになります。
指定先:src > main > resource > templates > book > add.html
HTMLの作成
form.html
フォームは登録画面と更新画面で共通に使う部分があるので、その部分は共通フォームとして作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> </head> <body> <div th:fragment="form"> <table> <tr> <td>書籍名</td> <td><input type="text" name="name" th:value="*{name}"> <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span> </td> </tr> <tr> <td>ISBNコード</td> <td><input type="text" name="isbn" th:value="*{isbn}"> <span th:if="${#fields.hasErrors('isbn')}" th:errors="*{isbn}"></span> </td> </tr> <tr><td>内容</td><td><textarea cols="22" rows="5" name="description" th:text="*{description}"></textarea></td></tr> <tr> <td>出版社</td> <td> <input type="text" name="publisher" th:value="*{publisher}"> <span th:if="${#fields.hasErrors('publisher')}" th:errors="*{publisher}"></span> </td> </tr> <tr> <td>価格</td> <td> <input type="number" name="price" th:value="*{price}"> <span th:if="${#fields.hasErrors('price')}" th:errors="*{price}"></span> </td> </tr> <tr> <td>出版年月日</td> <td> <input type="date" name="publication_date" th:value="${bookForm.publicationDateYmd()}"> <span th:if="${#fields.hasErrors('publication_date')}" th:errors="*{publication_date}"></span> </td> </tr> </table> <input type="hidden" name="id" th:value="*{id}" > <span th:if="${#fields.hasErrors('id')}" th:errors="*{id}"></span> <input type="hidden" name="version" th:value="*{version}" > </div> </body> </html> |
・<html xmlns:th=”http://www.thymeleaf.org”>
IDEがth:*属性の名前定義についてHTML5の仕様として有効でない警告を発することへの対応です。
<html>としても動作に影響はありませんが、警告を表示させないために指定しておきます。
引用元:3.1 複数言語でウェルカム
・th:value
th:objectで指定されているオブジェクトのフィールド名に対応していた値が代入されます。
th:objectは、以降のadd.htmlで定義します。
・th:if=”${#fields.hasErrors(…)}” th:errors=”*{…}”
指定したフィールドにバリデーションエラーがある場合に、エラー内容を表示します。
・type=”hidden”
id、version値は画面で操作する値ではありませんが、リクエストする値として必要(更新時)なのでフォームにhidden(非表示)で保持させます。
登録時は保持していないので、空の値を持っていることになります。
add.html
登録画面固有の定義と共通ヘッダー/共通フォームの埋め込みを行います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head th:replace="header::head(~{::title})"> <title>書籍情報登録</title> </head> <body> <header th:replace="header::header"></header> <div> <form th:action="@{/book/create}" th:object="${bookForm}" method="post"> <div th:insert="book/form"></div> <button type="submit">登録</button> </form> </div> </body> </html> |
・共通ヘッダー部の埋め込み
- タイトルを設定するために、titleタグに「書籍情報登録」とします。
- 共通ヘッダーのリンク(header::header)をth:replaceで置換するようにします。
・共通フォームの埋め込み
<div th:insert=”book/form”></div>
divタグ内に挿入(insert)する形で埋め込みます。
th:insertの場合、add.htmlのdivの中に埋め込まれます。
共通ヘッダーではth:replaceであるため、add.htmlのheaderタグがheader.htmlのheaderタグで置換されていました。
・th:object
サーバサイドからフォーム上に渡されるオブジェクトです。
登録画面の初期表示の場合、各フィールドがNULLのオブジェクトが渡されるため空欄になっています。
登録処理でエラーが発生した場合、入力データを画面に再表示させることができます。
また、今後作成する更新画面であれば、初期表示時にデータを表示することもできます。
動作確認
index画面の「新規登録」をクリックすると、「http://localhost:8080/book/add」に遷移します。
以下が確認できればOKです。
・titleが「書籍情報登録」となっていること
・共通ヘッダーが表示されていること
・共通フォーム(書籍名など)が表示されていること
・登録ボタンが配置されていること
まとめ
・画面とController間での値の受け渡しにFormを利用する。
・Controllerとして使用するクラスには、@Controllerアノテーションを付ける。
・リクエストのマッピングでにおいて、Getメソッドであれば@GetMappingとし、URLはカッコ内に指定する。
・遷移先はtemplates配下のディレクトリとファイル名で指定する(book/addなど)。
・登録画面と更新画面でフォームが共通である場合は部品化しておくとよい。
・thymeleafのth:属性で受け取った値に対する操作が可能になる。
次回は登録処理を実装していきます。