Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その30 )( 貸出申請画面の作成 )
概要
Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その29 )( 貸出状況取得タスクの作成3 ) の続きです。
- 貸出申請画面を作成します。5~6回に分けて書きます。
- 今回の手順で確認できるのは以下の内容です。
- 貸出申請画面の作成
- Thymeleaf テンプレートファイルと Controller クラスの雛形の作成
- 貸出申請画面の作成
参照したサイト・書籍
目次
- はじめに
- feature/43-issue ブランチの作成
- 貸出申請画面の HTML ファイルの作成
- Thymeleaf テンプレートファイルの作成
- LendingAppController クラスの作成
- 動作確認
- 次回は。。。
手順
はじめに
全てのユーザが使用できる貸出申請画面を作成します。以下の仕様の想定です。
- 貸出状況取得タスクから送信されたメールに表示されている URL にアクセスして、パラメータで指定されている貸出申請 ID の書籍と貸出状況の一覧を表示します。
- 書籍毎に貸出希望の「する」「しない」のドロップダウンリストと理由記入の入力フィールドを表示します。Spring Boot で書籍の貸出状況確認・貸出申請する Web アプリケーションを作る ( その1 )( 概要 ) では貸出希望はチェックボックスにする予定でしたが、ドロップダウンリストのサンプルを作成したいので変更します。
- 貸出希望の書籍は「する」を選択して理由を記入した後、「申請」ボタンをクリックします。
- 最後に表示した貸出申請の ID を Cookie に保存しておき、URL を指定せずにログインした場合には前回表示していた貸出申請画面が表示されるようにします。
- 「一時保存」ボタンを用意し、クリックされたら現在入力中のチェック、理由をセッションに保存し、同じ貸出申請 ID の画面が表示された場合には保存しておいたチェック、理由が再現されるようにします。
- 承認権限 ( ROLE_APPROVER ) を持つユーザにメールを送信します。
feature/43-issue ブランチの作成
- feature/43-issue ブランチを作成します。
貸出申請画面の HTML ファイルの作成
src/main/resources/static/html の下に lendingapp.html を作成します。作成後、リンク先の内容 に変更します。
html には記述していませんが、申請後は修正できないようにします。
■申請前
■申請後
一旦 commit します。
Thymeleaf テンプレートファイルの作成
src/main/resources/templates の下に lendingapp ディレクトリを作成します。
src/main/resources/static/html/lendingapp.html を src/main/resources/templates/lendingapp の下にコピーします。
src/main/resources/templates/lendingapp の下の templates/lendingapp/lendingapp.html を リンク先の内容 に変更します。
一旦 commit します。
LendingAppController クラスの作成
src/main/java/ksbysample/webapp/lending/web の下に lendingapp パッケージを作成します。
src/main/java/ksbysample/webapp/lending/web/lendingapp の下に LendingappController.java を作成します。作成後、リンク先の内容 に変更します。
動作確認
Gradle projects View から bootRun タスクを実行して Tomcat を起動します。
ブラウザを起動し http://localhost:8080/lendingapp へアクセスします。最初はログイン画面が表示されますので ID に "tanaka.taro@sample.com"、Password に "taro" を入力して、「次回から自動的にログインする」をチェックせずに「ログイン」ボタンをクリックします。
以下の画面が表示されることを確認します。
「申請」ボタン、「一時保存」ボタンをクリックしても同じ画面が表示されることを確認します。
Ctrl+F2 を押して Tomcat を停止します。
一旦 commit します。
次回は。。。
パラメータで指定されている貸出申請 ID の書籍と貸出状況の一覧を DB から取得して表示する処理を実装します。
ソースコード
static/html/lendingapp.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>貸出申請</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <!-- Bootstrap 3.3.4 --> <link href="/css/bootstrap.min.css" rel="stylesheet" type="text/css"/> <!-- Font Awesome Icons --> <link href="/css/font-awesome.min.css" rel="stylesheet" type="text/css"/> <!-- Ionicons --> <link href="/css/ionicons.min.css" rel="stylesheet" type="text/css"/> <!-- Theme style --> <link href="/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/> <!-- AdminLTE Skins. Choose a skin from the css/skins folder instead of downloading all of them to reduce the load. --> <link href="/css/skins/_all-skins.min.css" rel="stylesheet" type="text/css"/> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="/js/html5shiv.min.js"></script> <script src="/js/respond.min.js"></script> <![endif]--> <style> .content-wrapper { background-color: #fffafa; } .selected-library { color: #ffffff !important; font-size: 100%; font-weight: 700; } .box-body.no-padding { padding-bottom: 10px !important; } .table>tbody>tr>td , .table>tbody>tr>th , .table>tfoot>tr>td , .table>tfoot>tr>th , .table>thead>tr>td , .table>thead>tr>th { padding: 5px; font-size: 90%; } .jp-gothic { font-family: Verdana, "游ゴシック", YuGothic, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif; } </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <header class="main-header"> <nav class="navbar navbar-static-top"> <div class="container"> <div class="navbar-header"> <a href="#" class="navbar-brand"><b>ksbysample-lending</b></a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse"> <i class="fa fa-bars"></i> </button> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div class="collapse navbar-collapse pull-left" id="navbar-collapse"> <ul class="nav navbar-nav"> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">メニュー <span class="caret"></span></a> <ul class="dropdown-menu" role="menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li class="divider"></li> <li><a href="#">Separated link</a></li> <li class="divider"></li> <li><a href="#">One more separated link</a></li> </ul> </li> </ul> </div> <!-- /.navbar-collapse --> <!-- Navbar Right Menu --> <div class="navbar-custom-menu"> <p class="navbar-text selected-library">選択中:テスト図書館</p> <ul class="nav navbar-nav"> <li><a href="#">ログアウト</a></li> </ul> </div> <!-- /.navbar-custom-menu --> </div> <!-- /.container-fluid --> </nav> </header> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Content Header (Page header) --> <section class="content-header"> <h1>貸出申請</h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-body no-padding"> <div class="col-xs-6 no-padding"> <table class="table table-bordered"> <colgroup> <col width="30%"/> <col width="70%"/> </colgroup> <tr> <th class="bg-purple">貸出申請ID</th> <th>1</th> </tr> <tr> <th class="bg-purple">ステータス</th> <th>申請中</th> </tr> </table> </div> <br/> <form id="lendingappForm" method="post" action=""> <table class="table table-hover"> <colgroup> <col width="5%"/> <col width="20%"/> <col width="20%"/> <col width="15%"/> <col width="15%"/> <col width="25%"/> </colgroup> <thead class="bg-purple"> <tr> <th>No.</th> <th>ISBN</th> <th>書名</th> <th>貸出状況</th> <th>申請</th> <th>申請理由</th> </tr> </thead> <tbody class="jp-gothic"> <tr> <th>1</th> <th>978-1-4302-5908-4</th> <th>Spring Recipes</th> <th>蔵書なし</th> <th> </th> <th> </th> </tr> <tr> <th>2</th> <th>978-4-7741-5380-3</th> <th>Spring3入門</th> <th>貸出可</th> <th> <select name="type" class="form-control input-sm"> <option value="">しない</option> <option value="1">する</option> </select> </th> <th> <input type="text" name="reason" class="form-control input-sm" value=""/> </th> </tr> <tr> <th>3</th> <th>978-4-87311-718-8</th> <th>Javaパフォーマンス</th> <th>貸出可</th> <th> <select name="type" class="form-control input-sm"> <option value="">しない</option> <option value="1">する</option> </select> </th> <th> <input type="text" name="reason" class="form-control input-sm" value=""/> </th> </tr> </tbody> </table> <div class="text-center"> <button class="btn bg-blue"><i class="fa fa-thumbs-up"></i> 申請</button> <button class="btn bg-orange"><i class="fa fa-tag"></i> 一時保存(まだ申請しない)</button> </div> </form> </div> </div> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <!-- jQuery 2.1.4 --> <script src="/js/jQuery-2.1.4.min.js" type="text/javascript"></script> <!-- Bootstrap 3.3.2 JS --> <script src="/js/bootstrap.min.js" type="text/javascript"></script> <!-- AdminLTE App --> <script src="/js/app.min.js" type="text/javascript"></script> </body> </html>
templates/lendingapp/lendingapp.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <title>貸出申請</title> <!-- Tell the browser to be responsive to screen width --> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/> <link th:replace="common/head-cssjs"/> <style> .content-wrapper { background-color: #fffafa; } .selected-library { color: #ffffff !important; font-size: 100%; font-weight: 700; } .box-body.no-padding { padding-bottom: 10px !important; } .table>tbody>tr>td , .table>tbody>tr>th , .table>tfoot>tr>td , .table>tfoot>tr>th , .table>thead>tr>td , .table>thead>tr>th { padding: 5px; font-size: 90%; } .jp-gothic { font-family: Verdana, "游ゴシック", YuGothic, "Hiragino Kaku Gothic ProN", Meiryo, sans-serif; } </style> </head> <!-- ADD THE CLASS layout-top-nav TO REMOVE THE SIDEBAR. --> <body class="skin-blue layout-top-nav"> <div class="wrapper"> <!-- Main Header --> <div th:replace="common/mainparts :: main-header"></div> <!-- Full Width Column --> <div class="content-wrapper"> <div class="container"> <!-- Content Header (Page header) --> <section class="content-header"> <h1>貸出申請</h1> </section> <!-- Main content --> <section class="content"> <div class="row"> <div class="col-xs-12"> <div class="box"> <div class="box-body no-padding"> <div class="col-xs-6 no-padding"> <table class="table table-bordered"> <colgroup> <col width="30%"/> <col width="70%"/> </colgroup> <tr> <th class="bg-purple">貸出申請ID</th> <th>1</th> </tr> <tr> <th class="bg-purple">ステータス</th> <th>申請中</th> </tr> </table> </div> <br/> <form id="lendingappForm" method="post" action="/lendingapp/apply" th:action="@{/lendingapp/apply}" th:object="${lendingappForm}"> <table class="table table-hover"> <colgroup> <col width="5%"/> <col width="20%"/> <col width="20%"/> <col width="15%"/> <col width="15%"/> <col width="25%"/> </colgroup> <thead class="bg-purple"> <tr> <th>No.</th> <th>ISBN</th> <th>書名</th> <th>貸出状況</th> <th>申請</th> <th>申請理由</th> </tr> </thead> <tbody class="jp-gothic"> <tr> <th>1</th> <th>978-1-4302-5908-4</th> <th>Spring Recipes</th> <th>蔵書なし</th> <th> </th> <th> </th> </tr> <tr> <th>2</th> <th>978-4-7741-5380-3</th> <th>Spring3入門</th> <th>貸出可</th> <th> <select name="type" class="form-control input-sm"> <option value="">しない</option> <option value="1">する</option> </select> </th> <th> <input type="text" name="reason" class="form-control input-sm" value=""/> </th> </tr> <tr> <th>3</th> <th>978-4-87311-718-8</th> <th>Javaパフォーマンス</th> <th>貸出可</th> <th> <select name="type" class="form-control input-sm"> <option value="">しない</option> <option value="1">する</option> </select> </th> <th> <input type="text" name="reason" class="form-control input-sm" value=""/> </th> </tr> </tbody> </table> <div class="text-center"> <button class="btn bg-blue js-btn-apply"><i class="fa fa-thumbs-up"></i> 申請</button> <button class="btn bg-orange js-btn-temporarySave"><i class="fa fa-tag"></i> 一時保存(まだ申請しない)</button> </div> </form> </div> </div> </div> </div> </section> <!-- /.content --> </div> <!-- /.container --> </div> </div> <!-- ./wrapper --> <script th:replace="common/bottom-js"></script> <script type="text/javascript"> <!-- $(document).ready(function() { $(".js-btn-apply").click(function(){ $("#lendingappForm").submit(); return false; }); $(".js-btn-temporarySave").click(function(){ $("#lendingappForm").attr("action", "/lendingapp/temporarySave"); $("#lendingappForm").submit(); return false; }); }); --> </script> </body> </html>
<html>
→<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
へ変更します。<!-- Bootstrap 3.3.4 --> ... <script src="/js/respond.min.js"></script><![endif]-->
→<link th:replace="common/head-cssjs"/>
へ変更します。<header class="main-header"> ... </header>
→<div th:replace="common/mainparts :: main-header"></div>
へ変更します。<form id="lendingappForm" method="post" action="">
→<form id="lendingappForm" method="post" action="/lendingapp/apply" th:action="@{/lendingapp/apply}" th:object="${lendingappForm}">
へ変更します。<button class="btn bg-blue">... 申請</button>
→<button class="btn bg-blue js-btn-apply">... 申請</button>
へ変更します。<button class="btn bg-orange">... 一時保存(まだ申請しない)</button>
→<button class="btn bg-orange js-btn-temporarySave">... 一時保存(まだ申請しない)</button>
へ変更します。<!-- jQuery 2.1.4 --> ... <script src="/js/app.min.js" type="text/javascript"></script>
→<script th:replace="common/bottom-js"></script>
へ変更します。</body>
の前に<script type="text/javascript"> ... </script>
を追加します。
LendingappController.java
package ksbysample.webapp.lending.web.lendingapp; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/lendingapp") public class LendingappController { @RequestMapping public String index() { return "lendingapp/lendingapp"; } @RequestMapping(value = "/apply", method = RequestMethod.POST) public String apply() { return "lendingapp/lendingapp"; } @RequestMapping(value = "/temporarySave", method = RequestMethod.POST) public String temporarySave() { return "lendingapp/lendingapp"; } }
- 今回から POST メソッドしか受け付けない URL には method 属性を記述することにします。
履歴
2015/11/15
初版発行。