Spring Boot Ajax/JavaScript連携

Spring BootでのSubmit処理をJavaScriptで実施してみた

これまでは、フォームと呼ばれるブロックの値を送信するSubmit処理をFormタグのaction属性で行っていたが、今回はJavaScriptによるSubmit処理を行ってみたので、そのサンプルプログラムを共有する。

前提条件

下記記事の実装が完了していること。

Spring Bootで全角チェック処理を行う独自アノテーションを作成してみたSpring Bootの独自アノテーションで、特定のフィールドに対するチェック処理も実装することができる。今回は、特定のフィールドの全角...

サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加/変更したプログラムである。

今回追加したJavaScriptファイルの内容は以下の通りで、引数に指定されたパスをaction属性(送信先)としてSubmitしている。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
'use strict';
// 引数で指定されたパスでサブミットする
function formSubmit(path){
if(!path){
alert('パスを指定してください');
return;
}
let form = document.getElementsByTagName('form')[0];
if(!form){
alert('フォームが取得できませんでした');
return;
}
form.action=path;
form.method="post";
form.submit();
}
'use strict'; // 引数で指定されたパスでサブミットする function formSubmit(path){ if(!path){ alert('パスを指定してください'); return; } let form = document.getElementsByTagName('form')[0]; if(!form){ alert('フォームが取得できませんでした'); return; } form.action=path; form.method="post"; form.submit(); }
'use strict';

// 引数で指定されたパスでサブミットする
function formSubmit(path){
    if(!path){
        alert('パスを指定してください');
        return;
    }
    let form = document.getElementsByTagName('form')[0];
    if(!form){
        alert('フォームが取得できませんでした');
        return;
    }
    form.action=path;
    form.method="post";
    form.submit();
}
Code VillageはJavaScriptを中心としたサポート体制が充実したプログラミングスクールだったJavaScriptや、JavaScriptのフレームワーク「React」「Vue」を中心にオンラインで学習できるプログラミングスクール...

また、各HTMLファイルの内容は以下の通りで、先ほどのJavaScriptファイルを読み込み、ボタンが押下されたタイミングでformSubmit関数を呼び出すようにしている。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link th:href="@{/demo.css}" rel="stylesheet" type="text/css" />
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>index page</title>
</head>
<body>
<p>検索条件を指定し、「検索」ボタンを押下してください。</p><br/>
<form th:object="${searchForm}">
<!-- 2行エラーがある場合は、エラーメッセージを改行して表示 -->
<span th:if="*{#fields.hasErrors('fromBirthYear')}"
th:errors="*{fromBirthYear}" class="errorMessage"></span>
<span th:if="*{#fields.hasErrors('fromBirthYear') && #fields.hasErrors('toBirthYear')}">
<br/>
</span>
<span th:if="*{#fields.hasErrors('toBirthYear')}"
th:errors="*{toBirthYear}" class="errorMessage"></span>
<table border="1" cellpadding="5">
<tr>
<th>名前</th>
<td><input type="text" th:value="*{searchName}" th:field="*{searchName}" /></td>
</tr>
<tr>
<th>生年月日</th>
<td><input type="text" th:value="*{fromBirthYear}" size="4"
maxlength="4" th:field="*{fromBirthYear}" th:errorclass="fieldError"/>
<select th:field="*{fromBirthMonth}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'">
<option value=""></option>
<option th:each="item : *{getMonthItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
<select th:field="*{fromBirthDay}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'">
<option value=""></option>
<option th:each="item : *{getDayItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>日~
<input type="text" th:value="*{toBirthYear}" size="4"
maxlength="4" th:field="*{toBirthYear}" th:errorclass="fieldError"/>
<select th:field="*{toBirthMonth}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'">
<option value=""></option>
<option th:each="item : *{getMonthItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
<select th:field="*{toBirthDay}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'">
<option value=""></option>
<option th:each="item : *{getDayItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
</td>
</tr>
<tr>
<th>性別</th>
<td>
<select th:field="*{searchSex}">
<option value=""></option>
<option th:each="item : *{getSexItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
</td>
</tr>
</table>
<br/><br/>
<input type="button" value="検索" onclick="formSubmit('/search');" /><br/><br/>
<input type="button" value="閉じる" onclick="window.close();" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <link th:href="@{/demo.css}" rel="stylesheet" type="text/css" /> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>index page</title> </head> <body> <p>検索条件を指定し、「検索」ボタンを押下してください。</p><br/> <form th:object="${searchForm}"> <!-- 2行エラーがある場合は、エラーメッセージを改行して表示 --> <span th:if="*{#fields.hasErrors('fromBirthYear')}" th:errors="*{fromBirthYear}" class="errorMessage"></span> <span th:if="*{#fields.hasErrors('fromBirthYear') && #fields.hasErrors('toBirthYear')}"> <br/> </span> <span th:if="*{#fields.hasErrors('toBirthYear')}" th:errors="*{toBirthYear}" class="errorMessage"></span> <table border="1" cellpadding="5"> <tr> <th>名前</th> <td><input type="text" th:value="*{searchName}" th:field="*{searchName}" /></td> </tr> <tr> <th>生年月日</th> <td><input type="text" th:value="*{fromBirthYear}" size="4" maxlength="4" th:field="*{fromBirthYear}" th:errorclass="fieldError"/>年 <select th:field="*{fromBirthMonth}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'"> <option value=""></option> <option th:each="item : *{getMonthItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>月 <select th:field="*{fromBirthDay}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'"> <option value=""></option> <option th:each="item : *{getDayItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>日~ <input type="text" th:value="*{toBirthYear}" size="4" maxlength="4" th:field="*{toBirthYear}" th:errorclass="fieldError"/>年 <select th:field="*{toBirthMonth}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'"> <option value=""></option> <option th:each="item : *{getMonthItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>月 <select th:field="*{toBirthDay}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'"> <option value=""></option> <option th:each="item : *{getDayItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>日 </td> </tr> <tr> <th>性別</th> <td> <select th:field="*{searchSex}"> <option value=""></option> <option th:each="item : *{getSexItems()}" th:value="${item.key}" th:text="${item.value}"/> </select> </td> </tr> </table> <br/><br/> <input type="button" value="検索" onclick="formSubmit('/search');" /><br/><br/> <input type="button" value="閉じる" onclick="window.close();" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link th:href="@{/demo.css}" rel="stylesheet" type="text/css" />
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>index page</title>
</head>
<body>
    <p>検索条件を指定し、「検索」ボタンを押下してください。</p><br/>
    <form th:object="${searchForm}">
        <!-- 2行エラーがある場合は、エラーメッセージを改行して表示 -->
        <span th:if="*{#fields.hasErrors('fromBirthYear')}"
              th:errors="*{fromBirthYear}" class="errorMessage"></span>
        <span th:if="*{#fields.hasErrors('fromBirthYear') && #fields.hasErrors('toBirthYear')}">
            <br/>
        </span>
        <span th:if="*{#fields.hasErrors('toBirthYear')}"
              th:errors="*{toBirthYear}" class="errorMessage"></span>
        <table border="1" cellpadding="5">
            <tr>
                <th>名前</th>
                <td><input type="text" th:value="*{searchName}" th:field="*{searchName}" /></td>
            </tr>
            <tr>
                <th>生年月日</th>
                <td><input type="text" th:value="*{fromBirthYear}" size="4"
                           maxlength="4" th:field="*{fromBirthYear}" th:errorclass="fieldError"/>年
                    <select th:field="*{fromBirthMonth}" th:errorclass="fieldError"
                            th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'">
                        <option value=""></option>
                        <option th:each="item : *{getMonthItems()}"
                                th:value="${item.key}" th:text="${item.value}"/>
                    </select>月
                    <select th:field="*{fromBirthDay}" th:errorclass="fieldError"
                            th:classappend="${#fields.hasErrors('fromBirthYear')} ? 'fieldError'">
                        <option value=""></option>
                        <option th:each="item : *{getDayItems()}"
                                th:value="${item.key}" th:text="${item.value}"/>
                    </select>日~
                    <input type="text" th:value="*{toBirthYear}" size="4"
                           maxlength="4" th:field="*{toBirthYear}" th:errorclass="fieldError"/>年
                    <select th:field="*{toBirthMonth}" th:errorclass="fieldError"
                            th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'">
                        <option value=""></option>
                        <option th:each="item : *{getMonthItems()}"
                                th:value="${item.key}" th:text="${item.value}"/>
                    </select>月
                    <select th:field="*{toBirthDay}" th:errorclass="fieldError"
                            th:classappend="${#fields.hasErrors('toBirthYear')} ? 'fieldError'">
                        <option value=""></option>
                        <option th:each="item : *{getDayItems()}"
                                th:value="${item.key}" th:text="${item.value}"/>
                    </select>日
                </td>
            </tr>
            <tr>
                <th>性別</th>
                <td>
                    <select th:field="*{searchSex}">
                        <option value=""></option>
                        <option th:each="item : *{getSexItems()}"
                                th:value="${item.key}" th:text="${item.value}"/>
                    </select>
                </td>
            </tr>
        </table>
        <br/><br/>
        <input type="button" value="検索" onclick="formSubmit('/search');" /><br/><br/>
        <input type="button" value="閉じる" onclick="window.close();" />
    </form>
</body>
</html>
「HD Video Converter Factory Pro」は動画の形式変換や編集・録画等を行える便利ツールだった動画の形式変換や編集・録画等を行える便利ツールの一つに、「HD Video Converter Factory Pro」があります。ここ...
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>index page</title>
</head>
<body>
ユーザーデータテーブル(user_data)の全データ<br/><br/>
<table border="1" cellpadding="5">
<tr>
<th>ID</th>
<th>名前</th>
<th>生年月日</th>
<th>性別</th>
<th></th>
<th></th>
</tr>
<tr th:each="obj : ${demoFormList}">
<td th:text="${obj.id}"></td>
<td th:text="${obj.name}"></td>
<td th:text="|${obj.birthYear}年 ${obj.birthMonth}月 ${obj.birthDay}日|"></td>
<td th:text="${obj.sex_value}"></td>
<td><a href="/update" th:href="@{/update(id=${'__${obj.id}__'})}">更新</a></td>
<td><a href="/delete_confirm" th:href="@{/delete_confirm(id=${'__${obj.id}__'})}">削除</a></td>
</tr>
</table>
<br/><br/>
<table border="0">
<tr>
<td width="70">
<span th:if="${currentPageNum} != 1">
<a href="/firstPage" th:href="@{/firstPage}">先頭へ</a>
</span>
</td>
<td width="50">
<span th:if="${currentPageNum} != 1">
<a href="/backPage" th:href="@{/backPage}">前へ</a>
</span>
</td>
<td width="50">
<span th:text="${currentPageNum}"></span>&nbsp;/&nbsp;<span th:text="${allPageNum}"></span>
</td>
<td width="50">
<span th:if="${currentPageNum} != ${allPageNum}">
<a href="/nextPage" th:href="@{/nextPage}">次へ</a>
</span>
</td>
<td width="70">
<span th:if="${currentPageNum} != ${allPageNum}">
<a href="/lastPage" th:href="@{/lastPage}">最後へ</a>
</span>
</td>
</tr>
</table>
<br/><br/>
<form>
<input type="button" value="データ追加" onclick="formSubmit('/add');" /><br/><br/>
<input type="button" value="戻る" onclick="formSubmit('/addBack');" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>index page</title> </head> <body> ユーザーデータテーブル(user_data)の全データ<br/><br/> <table border="1" cellpadding="5"> <tr> <th>ID</th> <th>名前</th> <th>生年月日</th> <th>性別</th> <th></th> <th></th> </tr> <tr th:each="obj : ${demoFormList}"> <td th:text="${obj.id}"></td> <td th:text="${obj.name}"></td> <td th:text="|${obj.birthYear}年 ${obj.birthMonth}月 ${obj.birthDay}日|"></td> <td th:text="${obj.sex_value}"></td> <td><a href="/update" th:href="@{/update(id=${'__${obj.id}__'})}">更新</a></td> <td><a href="/delete_confirm" th:href="@{/delete_confirm(id=${'__${obj.id}__'})}">削除</a></td> </tr> </table> <br/><br/> <table border="0"> <tr> <td width="70"> <span th:if="${currentPageNum} != 1"> <a href="/firstPage" th:href="@{/firstPage}">先頭へ</a> </span> </td> <td width="50"> <span th:if="${currentPageNum} != 1"> <a href="/backPage" th:href="@{/backPage}">前へ</a> </span> </td> <td width="50"> <span th:text="${currentPageNum}"></span>&nbsp;/&nbsp;<span th:text="${allPageNum}"></span> </td> <td width="50"> <span th:if="${currentPageNum} != ${allPageNum}"> <a href="/nextPage" th:href="@{/nextPage}">次へ</a> </span> </td> <td width="70"> <span th:if="${currentPageNum} != ${allPageNum}"> <a href="/lastPage" th:href="@{/lastPage}">最後へ</a> </span> </td> </tr> </table> <br/><br/> <form> <input type="button" value="データ追加" onclick="formSubmit('/add');" /><br/><br/> <input type="button" value="戻る" onclick="formSubmit('/addBack');" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>index page</title>
</head>
<body>
    ユーザーデータテーブル(user_data)の全データ<br/><br/>

    <table border="1" cellpadding="5">
        <tr>
            <th>ID</th>
            <th>名前</th>
            <th>生年月日</th>
            <th>性別</th>
            <th></th>
            <th></th>
        </tr>
        <tr th:each="obj : ${demoFormList}">
            <td th:text="${obj.id}"></td>
            <td th:text="${obj.name}"></td>
            <td th:text="|${obj.birthYear}年 ${obj.birthMonth}月 ${obj.birthDay}日|"></td>
            <td th:text="${obj.sex_value}"></td>
            <td><a href="/update" th:href="@{/update(id=${'__${obj.id}__'})}">更新</a></td>
            <td><a href="/delete_confirm" th:href="@{/delete_confirm(id=${'__${obj.id}__'})}">削除</a></td>
        </tr>
    </table>
    <br/><br/>
    <table border="0">
        <tr>
            <td width="70">
                <span th:if="${currentPageNum} != 1">
                    <a href="/firstPage" th:href="@{/firstPage}">先頭へ</a>
                </span>
            </td>
            <td width="50">
                <span th:if="${currentPageNum} != 1">
                    <a href="/backPage" th:href="@{/backPage}">前へ</a>
                </span>
            </td>
            <td width="50">
                <span th:text="${currentPageNum}"></span>&nbsp;/&nbsp;<span th:text="${allPageNum}"></span>
            </td>
            <td width="50">
                <span th:if="${currentPageNum} != ${allPageNum}">
                    <a href="/nextPage" th:href="@{/nextPage}">次へ</a>
                </span>
            </td>
            <td width="70">
                <span th:if="${currentPageNum} != ${allPageNum}">
                    <a href="/lastPage" th:href="@{/lastPage}">最後へ</a>
                </span>
            </td>
        </tr>
    </table>
    <br/><br/>
    <form>
        <input type="button" value="データ追加" onclick="formSubmit('/add');" /><br/><br/>
        <input type="button" value="戻る" onclick="formSubmit('/addBack');" />
    </form>
</body>
</html>



Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<link th:href="@{/demo.css}" rel="stylesheet" type="text/css" />
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>入力画面</title>
</head>
<body>
<p>下記必要事項を記載の上、「確認」ボタンを押下してください。</p><br/>
<form th:object="${demoForm}">
<table border="0">
<tr>
<td align="left" valign="top">名前:</td>
<td>
<input type="text" th:value="*{name}"
th:field="*{name}" th:errorclass="fieldError" />
<span th:if="*{#fields.hasErrors('name')}"
th:errors="*{name}" class="errorMessage"></span>
</td>
</tr>
<tr>
<td align="left" valign="top">生年月日:</td>
<td>
<input type="text" th:value="*{birthYear}" size="4"
maxlength="4" th:field="*{birthYear}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('birthDayRequired')} ? 'fieldError'" />
<select th:field="*{birthMonth}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('birthYear')
|| #fields.hasErrors('birthDayRequired')} ? 'fieldError'">
<option value="">---</option>
<option th:each="item : *{getMonthItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
<select th:field="*{birthDay}" th:errorclass="fieldError"
th:classappend="${#fields.hasErrors('birthYear')
|| #fields.hasErrors('birthDayRequired')} ? 'fieldError'">
<option value="">---</option>
<option th:each="item : *{getDayItems()}"
th:value="${item.key}" th:text="${item.value}"/>
</select>
<span th:if="*{#fields.hasErrors('birthDayRequired')}"
th:errors="*{birthDayRequired}" class="errorMessage"></span>
<span th:if="*{#fields.hasErrors('birthYear')}"
th:errors="*{birthYear}" class="errorMessage"></span>
</td>
</tr>
<tr>
<td align="left" valign="top">性別:</td>
<td>
<for th:each="item : *{getSexItems()}">
<input type="radio" name="sex" th:value="${item.key}" th:text="${item.value}"
th:field="*{sex}" th:errorclass="fieldError" />
</for>
<span th:if="*{#fields.hasErrors('sex')}"
th:errors="*{sex}" class="errorMessage"></span>
<span th:if="*{#fields.hasErrors('sexInvalid')}"
th:errors="*{sexInvalid}" class="errorMessage"></span>
</td>
</tr>
<tr>
<td align="left" valign="top">メモ:</td>
<td>
<textarea rows="6" cols="40" th:value="*{memo}" th:field="*{memo}"></textarea>
</td>
</tr>
<tr>
<td align="left" valign="top">入力確認:</td>
<td>
<input type="checkbox" name="checked" th:value="確認済"
th:field="*{checked}" th:errorclass="fieldError" />
<span th:if="*{#fields.hasErrors('checked')}"
th:errors="*{checked}" class="errorMessage"></span>
</td>
</tr>
</table>
<br/><br/>
<input type="button" value="確認" onclick="formSubmit('/confirm');" />
<input type="button" value="戻る" onclick="formSubmit('/confirmBack');" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <link th:href="@{/demo.css}" rel="stylesheet" type="text/css" /> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>入力画面</title> </head> <body> <p>下記必要事項を記載の上、「確認」ボタンを押下してください。</p><br/> <form th:object="${demoForm}"> <table border="0"> <tr> <td align="left" valign="top">名前:</td> <td> <input type="text" th:value="*{name}" th:field="*{name}" th:errorclass="fieldError" /> <span th:if="*{#fields.hasErrors('name')}" th:errors="*{name}" class="errorMessage"></span> </td> </tr> <tr> <td align="left" valign="top">生年月日:</td> <td> <input type="text" th:value="*{birthYear}" size="4" maxlength="4" th:field="*{birthYear}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('birthDayRequired')} ? 'fieldError'" />年 <select th:field="*{birthMonth}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('birthYear') || #fields.hasErrors('birthDayRequired')} ? 'fieldError'"> <option value="">---</option> <option th:each="item : *{getMonthItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>月 <select th:field="*{birthDay}" th:errorclass="fieldError" th:classappend="${#fields.hasErrors('birthYear') || #fields.hasErrors('birthDayRequired')} ? 'fieldError'"> <option value="">---</option> <option th:each="item : *{getDayItems()}" th:value="${item.key}" th:text="${item.value}"/> </select>日 <span th:if="*{#fields.hasErrors('birthDayRequired')}" th:errors="*{birthDayRequired}" class="errorMessage"></span> <span th:if="*{#fields.hasErrors('birthYear')}" th:errors="*{birthYear}" class="errorMessage"></span> </td> </tr> <tr> <td align="left" valign="top">性別:</td> <td> <for th:each="item : *{getSexItems()}"> <input type="radio" name="sex" th:value="${item.key}" th:text="${item.value}" th:field="*{sex}" th:errorclass="fieldError" /> </for> <span th:if="*{#fields.hasErrors('sex')}" th:errors="*{sex}" class="errorMessage"></span> <span th:if="*{#fields.hasErrors('sexInvalid')}" th:errors="*{sexInvalid}" class="errorMessage"></span> </td> </tr> <tr> <td align="left" valign="top">メモ:</td> <td> <textarea rows="6" cols="40" th:value="*{memo}" th:field="*{memo}"></textarea> </td> </tr> <tr> <td align="left" valign="top">入力確認:</td> <td> <input type="checkbox" name="checked" th:value="確認済" th:field="*{checked}" th:errorclass="fieldError" /> <span th:if="*{#fields.hasErrors('checked')}" th:errors="*{checked}" class="errorMessage"></span> </td> </tr> </table> <br/><br/> <input type="button" value="確認" onclick="formSubmit('/confirm');" /> <input type="button" value="戻る" onclick="formSubmit('/confirmBack');" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <link th:href="@{/demo.css}" rel="stylesheet" type="text/css" />
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>入力画面</title>
</head>
<body>
    <p>下記必要事項を記載の上、「確認」ボタンを押下してください。</p><br/>
    <form th:object="${demoForm}">
       <table border="0">
           <tr>
               <td align="left" valign="top">名前:</td>
               <td>
                   <input type="text" th:value="*{name}"
                          th:field="*{name}" th:errorclass="fieldError" />
                   <span th:if="*{#fields.hasErrors('name')}"
                         th:errors="*{name}" class="errorMessage"></span>
               </td>
           </tr>
           <tr>
               <td align="left" valign="top">生年月日:</td>
               <td>
                   <input type="text" th:value="*{birthYear}" size="4"
                          maxlength="4" th:field="*{birthYear}" th:errorclass="fieldError"
                          th:classappend="${#fields.hasErrors('birthDayRequired')} ? 'fieldError'" />年
                   <select th:field="*{birthMonth}" th:errorclass="fieldError"
                           th:classappend="${#fields.hasErrors('birthYear')
                                || #fields.hasErrors('birthDayRequired')} ? 'fieldError'">
                       <option value="">---</option>
                       <option th:each="item : *{getMonthItems()}"
                               th:value="${item.key}" th:text="${item.value}"/>
                   </select>月
                   <select th:field="*{birthDay}" th:errorclass="fieldError"
                           th:classappend="${#fields.hasErrors('birthYear')
                                || #fields.hasErrors('birthDayRequired')} ? 'fieldError'">
                       <option value="">---</option>
                       <option th:each="item : *{getDayItems()}"
                               th:value="${item.key}" th:text="${item.value}"/>
                   </select>日
                   <span th:if="*{#fields.hasErrors('birthDayRequired')}"
                         th:errors="*{birthDayRequired}" class="errorMessage"></span>
                   <span th:if="*{#fields.hasErrors('birthYear')}"
                         th:errors="*{birthYear}" class="errorMessage"></span>
               </td>
           </tr>
           <tr>
               <td align="left" valign="top">性別:</td>
               <td>
                   <for th:each="item : *{getSexItems()}">
                       <input type="radio" name="sex" th:value="${item.key}" th:text="${item.value}"
                              th:field="*{sex}" th:errorclass="fieldError" />
                   </for>
                   <span th:if="*{#fields.hasErrors('sex')}"
                         th:errors="*{sex}" class="errorMessage"></span>
                   <span th:if="*{#fields.hasErrors('sexInvalid')}"
                         th:errors="*{sexInvalid}" class="errorMessage"></span>
               </td>
           </tr>
           <tr>
               <td align="left" valign="top">メモ:</td>
               <td>
                   <textarea rows="6" cols="40" th:value="*{memo}" th:field="*{memo}"></textarea>
               </td>
           </tr>
           <tr>
               <td align="left" valign="top">入力確認:</td>
               <td>
                   <input type="checkbox" name="checked" th:value="確認済"
                          th:field="*{checked}" th:errorclass="fieldError" />
                   <span th:if="*{#fields.hasErrors('checked')}"
                         th:errors="*{checked}" class="errorMessage"></span>
               </td>
           </tr>
       </table>
       <br/><br/>
       <input type="button" value="確認" onclick="formSubmit('/confirm');" />
       <input type="button" value="戻る" onclick="formSubmit('/confirmBack');" />
   </form>
</body>
</html>



Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>確認画面</title>
</head>
<body>
   <p>入力内容を確認し、問題なければ「送信」ボタンを押下してください。</p>
<form th:object="${demoForm}">
<table border="0">
<tr>
<td align="left" valign="top">名前: </td>
<td>
<span th:text="*{name}">
ここに名前が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">生年月日: </td>
<td>
<span th:text="*{birthYear} + '年'
+ *{getMonthItems().get('__*{birthMonth}__')} + '月'
+ *{getDayItems().get('__*{birthDay}__')} + '日'">
ここに生年月日が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">性別: </td>
<td>
<span th:text="*{getSexItems().get('__*{sex}__')}">
ここに性別が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">メモ: </td>
<td>
<th:block th:if="*{memo}">
<th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}">
<th:block th:text="${memoStr}"/>
<br th:if="${!memoStat.last}"/>
</th:block>
</th:block>
</td>
</tr>
<tr>
<td align="left" valign="top">確認チェック: </td>
<td>
<span th:text="*{checked}">
ここに確認チェック内容が表示されます
</span>
</td>
</tr>
</table>
<br/><br/>
<input type="button" value="送信" onclick="formSubmit('/send');" />
<input type="button" value="戻る" onclick="formSubmit('/sendBack');" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>確認画面</title> </head> <body>    <p>入力内容を確認し、問題なければ「送信」ボタンを押下してください。</p> <form th:object="${demoForm}"> <table border="0"> <tr> <td align="left" valign="top">名前: </td> <td> <span th:text="*{name}"> ここに名前が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">生年月日: </td> <td> <span th:text="*{birthYear} + '年' + *{getMonthItems().get('__*{birthMonth}__')} + '月' + *{getDayItems().get('__*{birthDay}__')} + '日'"> ここに生年月日が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">性別: </td> <td> <span th:text="*{getSexItems().get('__*{sex}__')}"> ここに性別が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">メモ: </td> <td> <th:block th:if="*{memo}"> <th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}"> <th:block th:text="${memoStr}"/> <br th:if="${!memoStat.last}"/> </th:block> </th:block> </td> </tr> <tr> <td align="left" valign="top">確認チェック: </td> <td> <span th:text="*{checked}"> ここに確認チェック内容が表示されます </span> </td> </tr> </table> <br/><br/> <input type="button" value="送信" onclick="formSubmit('/send');" /> <input type="button" value="戻る" onclick="formSubmit('/sendBack');" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>確認画面</title>
</head>
<body>
   <p>入力内容を確認し、問題なければ「送信」ボタンを押下してください。</p>
    <form th:object="${demoForm}">
        <table border="0">
            <tr>
                <td align="left" valign="top">名前: </td>
                <td>
                    <span th:text="*{name}">
                        ここに名前が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">生年月日: </td>
                <td>
                    <span th:text="*{birthYear} + '年'
                     + *{getMonthItems().get('__*{birthMonth}__')} + '月'
                     + *{getDayItems().get('__*{birthDay}__')} + '日'">
                        ここに生年月日が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">性別: </td>
                <td>
                    <span th:text="*{getSexItems().get('__*{sex}__')}">
                        ここに性別が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">メモ: </td>
                <td>
                    <th:block th:if="*{memo}">
                        <th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}">
                            <th:block th:text="${memoStr}"/>
                            <br th:if="${!memoStat.last}"/>
                        </th:block>
                    </th:block>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">確認チェック: </td>
                <td>
                    <span th:text="*{checked}">
                        ここに確認チェック内容が表示されます
                    </span>
                </td>
            </tr>
        </table>
        <br/><br/>
        <input type="button" value="送信" onclick="formSubmit('/send');" />
        <input type="button" value="戻る" onclick="formSubmit('/sendBack');" />
    </form>
</body>
</html>
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>完了画面</title>
</head>
<body>
   お申し込みが完了しました。<br/><br/>
<form>
<input type="button" value="検索画面に戻る" onclick="formSubmit('/');" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>完了画面</title> </head> <body>    お申し込みが完了しました。<br/><br/> <form> <input type="button" value="検索画面に戻る" onclick="formSubmit('/');" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>完了画面</title>
</head>
<body>
   お申し込みが完了しました。<br/><br/>

    <form>
        <input type="button" value="検索画面に戻る" onclick="formSubmit('/');" />
    </form>
</body>
</html>



Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<script type="text/javascript" th:src="@{/demo.js}"></script>
<title>削除確認画面</title>
</head>
<body>
   <p>下記内容を削除してよろしいでしょうか?問題なければ「送信」ボタンを押下してください。</p>
<form th:object="${demoForm}">
<table border="0">
<tr>
<td align="left" valign="top">名前: </td>
<td>
<span th:text="*{name}">
ここに名前が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">生年月日: </td>
<td>
<span th:text="*{birthYear} + '年'
+ *{getMonthItems().get('__*{birthMonth}__')} + '月'
+ *{getDayItems().get('__*{birthDay}__')} + '日'">
ここに生年月日が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">性別: </td>
<td>
<span th:text="*{getSexItems().get('__*{sex}__')}">
ここに性別が表示されます
</span>
</td>
</tr>
<tr>
<td align="left" valign="top">メモ: </td>
<td>
<th:block th:if="*{memo}">
<th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}">
<th:block th:text="${memoStr}"/>
<br th:if="${!memoStat.last}"/>
</th:block>
</th:block>
</td>
</tr>
</table>
<br/><br/>
<input type="button" value="送信" onclick="formSubmit('/delete');" />
<input type="button" value="戻る" onclick="formSubmit('/deleteBack');" />
</form>
</body>
</html>
<!DOCTYPE html> <html lang="ja" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <script type="text/javascript" th:src="@{/demo.js}"></script> <title>削除確認画面</title> </head> <body>    <p>下記内容を削除してよろしいでしょうか?問題なければ「送信」ボタンを押下してください。</p> <form th:object="${demoForm}"> <table border="0"> <tr> <td align="left" valign="top">名前: </td> <td> <span th:text="*{name}"> ここに名前が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">生年月日: </td> <td> <span th:text="*{birthYear} + '年' + *{getMonthItems().get('__*{birthMonth}__')} + '月' + *{getDayItems().get('__*{birthDay}__')} + '日'"> ここに生年月日が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">性別: </td> <td> <span th:text="*{getSexItems().get('__*{sex}__')}"> ここに性別が表示されます </span> </td> </tr> <tr> <td align="left" valign="top">メモ: </td> <td> <th:block th:if="*{memo}"> <th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}"> <th:block th:text="${memoStr}"/> <br th:if="${!memoStat.last}"/> </th:block> </th:block> </td> </tr> </table> <br/><br/> <input type="button" value="送信" onclick="formSubmit('/delete');" /> <input type="button" value="戻る" onclick="formSubmit('/deleteBack');" /> </form> </body> </html>
<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" th:src="@{/demo.js}"></script>
    <title>削除確認画面</title>
</head>
<body>
   <p>下記内容を削除してよろしいでしょうか?問題なければ「送信」ボタンを押下してください。</p>
    <form th:object="${demoForm}">
        <table border="0">
            <tr>
                <td align="left" valign="top">名前: </td>
                <td>
                    <span th:text="*{name}">
                        ここに名前が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">生年月日: </td>
                <td>
                    <span th:text="*{birthYear} + '年'
                     + *{getMonthItems().get('__*{birthMonth}__')} + '月'
                     + *{getDayItems().get('__*{birthDay}__')} + '日'">
                        ここに生年月日が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">性別: </td>
                <td>
                    <span th:text="*{getSexItems().get('__*{sex}__')}">
                        ここに性別が表示されます
                    </span>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">メモ: </td>
                <td>
                    <th:block th:if="*{memo}">
                        <th:block th:each="memoStr, memoStat : *{memo.split('\r\n|\r|\n', -1)}">
                            <th:block th:text="${memoStr}"/>
                            <br th:if="${!memoStat.last}"/>
                        </th:block>
                    </th:block>
                </td>
            </tr>
        </table>
        <br/><br/>
        <input type="button" value="送信" onclick="formSubmit('/delete');" />
        <input type="button" value="戻る" onclick="formSubmit('/deleteBack');" />
    </form>
</body>
</html>



さらに、コントローラクラスの内容は以下の通りで、@PostMappingアノテーションのparams属性を利用しない形に変更している。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.data.domain.Pageable;
import java.util.ArrayList;
import java.util.List;
@Controller
@SessionAttributes(types = {DemoForm.class, SearchForm.class})
public class DemoController {
/**
* Demoサービスクラスへのアクセス
*/
@Autowired
private DemoService demoService;
/**
* ユーザーデータテーブル(user_data)のデータを取得して返却する
* @return ユーザーデータリスト
*/
@ModelAttribute("demoFormList")
public List<DemoForm> userDataList(){
List<DemoForm> demoFormList = new ArrayList<>();
return demoFormList;
}
/**
* 追加・更新用Formオブジェクトを初期化して返却する
* @return 追加・更新用Formオブジェクト
*/
@ModelAttribute("demoForm")
public DemoForm createDemoForm(){
DemoForm demoForm = new DemoForm();
return demoForm;
}
/**
* 検索用Formオブジェクトを初期化して返却する
* @return 検索用Formオブジェクト
*/
@ModelAttribute("searchForm")
public SearchForm createSearchForm(){
SearchForm searchForm = new SearchForm();
return searchForm;
}
/**
* 初期表示(検索)画面に遷移する
* @return 検索画面へのパス
*/
@RequestMapping("/")
public String index(){
return "search";
}
/**
* 検索処理を行い、一覧画面に遷移する
* @param searchForm 検索用Formオブジェクト
* @param result バインド結果
* @param model Modelオブジェクト
* @return 一覧画面へのパス
*/
@PostMapping("/search")
public String search(@Validated SearchForm searchForm
, BindingResult result, Model model){
//検索用Formオブジェクトのチェック処理でエラーがある場合は、
//検索画面のままとする
if(result.hasErrors()){
return "search";
}
//現在ページ数を1ページ目に設定し、一覧画面に遷移する
searchForm.setCurrentPageNum(1);
return movePageInList(model, searchForm);
}
/**
* 一覧画面で「先頭へ」リンク押下時に次ページを表示する
* @param searchForm 検索用Formオブジェクト
* @param model Modelオブジェクト
* @return 一覧画面へのパス
*/
@GetMapping("/firstPage")
public String firstPage(SearchForm searchForm, Model model){
//現在ページ数を先頭ページに設定する
searchForm.setCurrentPageNum(1);
return movePageInList(model, searchForm);
}
/**
* 一覧画面で「前へ」リンク押下時に次ページを表示する
* @param searchForm 検索用Formオブジェクト
* @param model Modelオブジェクト
* @return 一覧画面へのパス
*/
@GetMapping("/backPage")
public String backPage(SearchForm searchForm, Model model){
//現在ページ数を前ページに設定する
searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() - 1);
return movePageInList(model, searchForm);
}
/**
* 一覧画面で「次へ」リンク押下時に次ページを表示する
* @param searchForm 検索用Formオブジェクト
* @param model Modelオブジェクト
* @return 一覧画面へのパス
*/
@GetMapping("/nextPage")
public String nextPage(SearchForm searchForm, Model model){
//現在ページ数を次ページに設定する
searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() + 1);
return movePageInList(model, searchForm);
}
/**
* 一覧画面で「最後へ」リンク押下時に次ページを表示する
* @param searchForm 検索用Formオブジェクト
* @param model Modelオブジェクト
* @return 一覧画面へのパス
*/
@GetMapping("/lastPage")
public String lastPage(SearchForm searchForm, Model model){
//現在ページ数を最終ページに設定する
searchForm.setCurrentPageNum(demoService.getAllPageNum(searchForm));
return movePageInList(model, searchForm);
}
/**
* 更新処理を行う画面に遷移する
* @param id 更新対象のID
* @param model Modelオブジェクト
* @return 入力・更新画面へのパス
*/
@GetMapping("/update")
public String update(@RequestParam("id") String id, Model model){
//更新対象のユーザーデータを取得
DemoForm demoForm = demoService.findById(id);
//ユーザーデータを更新
model.addAttribute("demoForm", demoForm);
return "input";
}
/**
* 削除確認画面に遷移する
* @param id 更新対象のID
* @param model Modelオブジェクト
* @return 削除確認画面へのパス
*/
@GetMapping("/delete_confirm")
public String delete_confirm(@RequestParam("id") String id, Model model){
//削除対象のユーザーデータを取得
DemoForm demoForm = demoService.findById(id);
//ユーザーデータを更新
model.addAttribute("demoForm", demoForm);
return "confirm_delete";
}
/**
* 削除処理を行う
* @param demoForm 追加・更新用Formオブジェクト
* @return 一覧画面の表示処理
*/
@PostMapping(value = "/delete")
public String delete(DemoForm demoForm){
//指定したユーザーデータを削除
demoService.deleteById(demoForm.getId());
//一覧画面に遷移
return "redirect:/to_index";
}
/**
* 削除完了後に一覧画面に戻る
* @param searchForm 検索用Formオブジェクト
* @param model Modelオブジェクト
* @return 一覧画面
*/
@GetMapping("/to_index")
public String toIndex(SearchForm searchForm, Model model){
//一覧画面に戻り、1ページ目のリストを表示する
searchForm.setCurrentPageNum(1);
return movePageInList(model, searchForm);
}
/**
* 削除確認画面から一覧画面に戻る
* @param model Modelオブジェクト
* @param searchForm 検索用Formオブジェクト
* @return 一覧画面
*/
@PostMapping(value = "/deleteBack")
public String confirmDeleteBack(Model model, SearchForm searchForm){
//一覧画面に戻る
return movePageInList(model, searchForm);
}
/**
* 追加処理を行う画面に遷移する
* @param model Modelオブジェクト
* @return 入力・更新画面へのパス
*/
@PostMapping(value = "/add")
public String add(Model model){
model.addAttribute("demoForm", new DemoForm());
return "input";
}
/**
* 追加処理を行う画面から検索画面に戻る
* @return 検索画面へのパス
*/
@PostMapping(value = "/addBack")
public String addBack(){
return "search";
}
/**
* エラーチェックを行い、エラーが無ければ確認画面に遷移し、
* エラーがあれば入力画面のままとする
* @param demoForm 追加・更新用Formオブジェクト
* @param result バインド結果
* @return 確認画面または入力画面へのパス
*/
@PostMapping(value = "/confirm")
public String confirm(@Validated DemoForm demoForm, BindingResult result){
//追加・更新用Formオブジェクトのチェック処理でエラーがある場合は、
//入力画面のままとする
if(result.hasErrors()){
return "input";
}
//エラーが無ければ確認画面に遷移する
return "confirm";
}
/**
* 一覧画面に戻る
* @param model Modelオブジェクト
* @param searchForm 検索用Formオブジェクト
* @return 一覧画面の表示処理
*/
@PostMapping(value = "/confirmBack")
public String confirmBack(Model model, SearchForm searchForm){
//一覧画面に戻る
return movePageInList(model, searchForm);
}
/**
* 完了画面に遷移する
* @param demoForm 追加・更新用Formオブジェクト
* @param result バインド結果
* @return 完了画面
*/
@PostMapping(value = "/send")
public String send(@Validated DemoForm demoForm, BindingResult result){
//チェック処理を行い、エラーがなければ、更新・追加処理を行う
if(result.hasErrors()){
return "input";
}
demoService.createOrUpdate(demoForm);
return "redirect:/complete";
}
/**
* 完了画面に遷移する
* @param sessionStatus セッションステータス
* @return 完了画面
*/
@GetMapping("/complete")
public String complete(SessionStatus sessionStatus){
//セッションオブジェクトを破棄
sessionStatus.setComplete();
return "complete";
}
/**
* 入力画面に戻る
* @return 入力画面
*/
@PostMapping(value = "/sendBack")
public String sendBack(){
return "input";
}
/**
* 一覧画面に戻り、指定した現在ページのリストを表示する
* @param model Modelオブジェクト
* @param searchForm 検索用Formオブジェクト
* @return 一覧画面の表示処理
*/
private String movePageInList(Model model, SearchForm searchForm){
//現在ページ数, 総ページ数を設定
model.addAttribute("currentPageNum", searchForm.getCurrentPageNum());
model.addAttribute("allPageNum", demoService.getAllPageNum(searchForm));
//ページング用オブジェクトを生成し、現在ページのユーザーデータリストを取得
Pageable pageable = demoService.getPageable(searchForm.getCurrentPageNum());
List<DemoForm> demoFormList = demoService.demoFormList(searchForm, pageable);
//ユーザーデータリストを更新
model.addAttribute("demoFormList", demoFormList);
return "list";
}
}
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.SessionAttributes; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.validation.BindingResult; import org.springframework.web.bind.support.SessionStatus; import org.springframework.data.domain.Pageable; import java.util.ArrayList; import java.util.List; @Controller @SessionAttributes(types = {DemoForm.class, SearchForm.class}) public class DemoController { /** * Demoサービスクラスへのアクセス */ @Autowired private DemoService demoService; /** * ユーザーデータテーブル(user_data)のデータを取得して返却する * @return ユーザーデータリスト */ @ModelAttribute("demoFormList") public List<DemoForm> userDataList(){ List<DemoForm> demoFormList = new ArrayList<>(); return demoFormList; } /** * 追加・更新用Formオブジェクトを初期化して返却する * @return 追加・更新用Formオブジェクト */ @ModelAttribute("demoForm") public DemoForm createDemoForm(){ DemoForm demoForm = new DemoForm(); return demoForm; } /** * 検索用Formオブジェクトを初期化して返却する * @return 検索用Formオブジェクト */ @ModelAttribute("searchForm") public SearchForm createSearchForm(){ SearchForm searchForm = new SearchForm(); return searchForm; } /** * 初期表示(検索)画面に遷移する * @return 検索画面へのパス */ @RequestMapping("/") public String index(){ return "search"; } /** * 検索処理を行い、一覧画面に遷移する * @param searchForm 検索用Formオブジェクト * @param result バインド結果 * @param model Modelオブジェクト * @return 一覧画面へのパス */ @PostMapping("/search") public String search(@Validated SearchForm searchForm , BindingResult result, Model model){ //検索用Formオブジェクトのチェック処理でエラーがある場合は、 //検索画面のままとする if(result.hasErrors()){ return "search"; } //現在ページ数を1ページ目に設定し、一覧画面に遷移する searchForm.setCurrentPageNum(1); return movePageInList(model, searchForm); } /** * 一覧画面で「先頭へ」リンク押下時に次ページを表示する * @param searchForm 検索用Formオブジェクト * @param model Modelオブジェクト * @return 一覧画面へのパス */ @GetMapping("/firstPage") public String firstPage(SearchForm searchForm, Model model){ //現在ページ数を先頭ページに設定する searchForm.setCurrentPageNum(1); return movePageInList(model, searchForm); } /** * 一覧画面で「前へ」リンク押下時に次ページを表示する * @param searchForm 検索用Formオブジェクト * @param model Modelオブジェクト * @return 一覧画面へのパス */ @GetMapping("/backPage") public String backPage(SearchForm searchForm, Model model){ //現在ページ数を前ページに設定する searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() - 1); return movePageInList(model, searchForm); } /** * 一覧画面で「次へ」リンク押下時に次ページを表示する * @param searchForm 検索用Formオブジェクト * @param model Modelオブジェクト * @return 一覧画面へのパス */ @GetMapping("/nextPage") public String nextPage(SearchForm searchForm, Model model){ //現在ページ数を次ページに設定する searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() + 1); return movePageInList(model, searchForm); } /** * 一覧画面で「最後へ」リンク押下時に次ページを表示する * @param searchForm 検索用Formオブジェクト * @param model Modelオブジェクト * @return 一覧画面へのパス */ @GetMapping("/lastPage") public String lastPage(SearchForm searchForm, Model model){ //現在ページ数を最終ページに設定する searchForm.setCurrentPageNum(demoService.getAllPageNum(searchForm)); return movePageInList(model, searchForm); } /** * 更新処理を行う画面に遷移する * @param id 更新対象のID * @param model Modelオブジェクト * @return 入力・更新画面へのパス */ @GetMapping("/update") public String update(@RequestParam("id") String id, Model model){ //更新対象のユーザーデータを取得 DemoForm demoForm = demoService.findById(id); //ユーザーデータを更新 model.addAttribute("demoForm", demoForm); return "input"; } /** * 削除確認画面に遷移する * @param id 更新対象のID * @param model Modelオブジェクト * @return 削除確認画面へのパス */ @GetMapping("/delete_confirm") public String delete_confirm(@RequestParam("id") String id, Model model){ //削除対象のユーザーデータを取得 DemoForm demoForm = demoService.findById(id); //ユーザーデータを更新 model.addAttribute("demoForm", demoForm); return "confirm_delete"; } /** * 削除処理を行う * @param demoForm 追加・更新用Formオブジェクト * @return 一覧画面の表示処理 */ @PostMapping(value = "/delete") public String delete(DemoForm demoForm){ //指定したユーザーデータを削除 demoService.deleteById(demoForm.getId()); //一覧画面に遷移 return "redirect:/to_index"; } /** * 削除完了後に一覧画面に戻る * @param searchForm 検索用Formオブジェクト * @param model Modelオブジェクト * @return 一覧画面 */ @GetMapping("/to_index") public String toIndex(SearchForm searchForm, Model model){ //一覧画面に戻り、1ページ目のリストを表示する searchForm.setCurrentPageNum(1); return movePageInList(model, searchForm); } /** * 削除確認画面から一覧画面に戻る * @param model Modelオブジェクト * @param searchForm 検索用Formオブジェクト * @return 一覧画面 */ @PostMapping(value = "/deleteBack") public String confirmDeleteBack(Model model, SearchForm searchForm){ //一覧画面に戻る return movePageInList(model, searchForm); } /** * 追加処理を行う画面に遷移する * @param model Modelオブジェクト * @return 入力・更新画面へのパス */ @PostMapping(value = "/add") public String add(Model model){ model.addAttribute("demoForm", new DemoForm()); return "input"; } /** * 追加処理を行う画面から検索画面に戻る * @return 検索画面へのパス */ @PostMapping(value = "/addBack") public String addBack(){ return "search"; } /** * エラーチェックを行い、エラーが無ければ確認画面に遷移し、 * エラーがあれば入力画面のままとする * @param demoForm 追加・更新用Formオブジェクト * @param result バインド結果 * @return 確認画面または入力画面へのパス */ @PostMapping(value = "/confirm") public String confirm(@Validated DemoForm demoForm, BindingResult result){ //追加・更新用Formオブジェクトのチェック処理でエラーがある場合は、 //入力画面のままとする if(result.hasErrors()){ return "input"; } //エラーが無ければ確認画面に遷移する return "confirm"; } /** * 一覧画面に戻る * @param model Modelオブジェクト * @param searchForm 検索用Formオブジェクト * @return 一覧画面の表示処理 */ @PostMapping(value = "/confirmBack") public String confirmBack(Model model, SearchForm searchForm){ //一覧画面に戻る return movePageInList(model, searchForm); } /** * 完了画面に遷移する * @param demoForm 追加・更新用Formオブジェクト * @param result バインド結果 * @return 完了画面 */ @PostMapping(value = "/send") public String send(@Validated DemoForm demoForm, BindingResult result){ //チェック処理を行い、エラーがなければ、更新・追加処理を行う if(result.hasErrors()){ return "input"; } demoService.createOrUpdate(demoForm); return "redirect:/complete"; } /** * 完了画面に遷移する * @param sessionStatus セッションステータス * @return 完了画面 */ @GetMapping("/complete") public String complete(SessionStatus sessionStatus){ //セッションオブジェクトを破棄 sessionStatus.setComplete(); return "complete"; } /** * 入力画面に戻る * @return 入力画面 */ @PostMapping(value = "/sendBack") public String sendBack(){ return "input"; } /** * 一覧画面に戻り、指定した現在ページのリストを表示する * @param model Modelオブジェクト * @param searchForm 検索用Formオブジェクト * @return 一覧画面の表示処理 */ private String movePageInList(Model model, SearchForm searchForm){ //現在ページ数, 総ページ数を設定 model.addAttribute("currentPageNum", searchForm.getCurrentPageNum()); model.addAttribute("allPageNum", demoService.getAllPageNum(searchForm)); //ページング用オブジェクトを生成し、現在ページのユーザーデータリストを取得 Pageable pageable = demoService.getPageable(searchForm.getCurrentPageNum()); List<DemoForm> demoFormList = demoService.demoFormList(searchForm, pageable); //ユーザーデータリストを更新 model.addAttribute("demoFormList", demoFormList); return "list"; } }
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.data.domain.Pageable;
import java.util.ArrayList;
import java.util.List;

@Controller
@SessionAttributes(types = {DemoForm.class, SearchForm.class})
public class DemoController {

    /**
     * Demoサービスクラスへのアクセス
     */
    @Autowired
    private DemoService demoService;

    /**
     * ユーザーデータテーブル(user_data)のデータを取得して返却する
     * @return ユーザーデータリスト
     */
    @ModelAttribute("demoFormList")
    public List<DemoForm> userDataList(){
        List<DemoForm> demoFormList = new ArrayList<>();
        return demoFormList;
    }

    /**
     * 追加・更新用Formオブジェクトを初期化して返却する
     * @return 追加・更新用Formオブジェクト
     */
    @ModelAttribute("demoForm")
    public DemoForm createDemoForm(){
        DemoForm demoForm = new DemoForm();
        return demoForm;
    }

    /**
     * 検索用Formオブジェクトを初期化して返却する
     * @return 検索用Formオブジェクト
     */
    @ModelAttribute("searchForm")
    public SearchForm createSearchForm(){
        SearchForm searchForm = new SearchForm();
        return searchForm;
    }

    /**
     * 初期表示(検索)画面に遷移する
     * @return 検索画面へのパス
     */
    @RequestMapping("/")
    public String index(){
        return "search";
    }

    /**
     * 検索処理を行い、一覧画面に遷移する
     * @param searchForm 検索用Formオブジェクト
     * @param result バインド結果
     * @param model Modelオブジェクト
     * @return 一覧画面へのパス
     */
    @PostMapping("/search")
    public String search(@Validated SearchForm searchForm
            , BindingResult result, Model model){
        //検索用Formオブジェクトのチェック処理でエラーがある場合は、
        //検索画面のままとする
        if(result.hasErrors()){
            return "search";
        }
        //現在ページ数を1ページ目に設定し、一覧画面に遷移する
        searchForm.setCurrentPageNum(1);
        return movePageInList(model, searchForm);
    }

    /**
     * 一覧画面で「先頭へ」リンク押下時に次ページを表示する
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @return 一覧画面へのパス
     */
    @GetMapping("/firstPage")
    public String firstPage(SearchForm searchForm, Model model){
        //現在ページ数を先頭ページに設定する
        searchForm.setCurrentPageNum(1);
        return movePageInList(model, searchForm);
    }

    /**
     * 一覧画面で「前へ」リンク押下時に次ページを表示する
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @return 一覧画面へのパス
     */
    @GetMapping("/backPage")
    public String backPage(SearchForm searchForm, Model model){
        //現在ページ数を前ページに設定する
        searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() - 1);
        return movePageInList(model, searchForm);
    }

    /**
     * 一覧画面で「次へ」リンク押下時に次ページを表示する
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @return 一覧画面へのパス
     */
    @GetMapping("/nextPage")
    public String nextPage(SearchForm searchForm, Model model){
        //現在ページ数を次ページに設定する
        searchForm.setCurrentPageNum(searchForm.getCurrentPageNum() + 1);
        return movePageInList(model, searchForm);
    }

    /**
     * 一覧画面で「最後へ」リンク押下時に次ページを表示する
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @return 一覧画面へのパス
     */
    @GetMapping("/lastPage")
    public String lastPage(SearchForm searchForm, Model model){
        //現在ページ数を最終ページに設定する
        searchForm.setCurrentPageNum(demoService.getAllPageNum(searchForm));
        return movePageInList(model, searchForm);
    }

    /**
     * 更新処理を行う画面に遷移する
     * @param id 更新対象のID
     * @param model Modelオブジェクト
     * @return 入力・更新画面へのパス
     */
    @GetMapping("/update")
    public String update(@RequestParam("id") String id, Model model){
        //更新対象のユーザーデータを取得
        DemoForm demoForm = demoService.findById(id);
        //ユーザーデータを更新
        model.addAttribute("demoForm", demoForm);
        return "input";
    }

    /**
     * 削除確認画面に遷移する
     * @param id 更新対象のID
     * @param model Modelオブジェクト
     * @return 削除確認画面へのパス
     */
    @GetMapping("/delete_confirm")
    public String delete_confirm(@RequestParam("id") String id, Model model){
        //削除対象のユーザーデータを取得
        DemoForm demoForm = demoService.findById(id);
        //ユーザーデータを更新
        model.addAttribute("demoForm", demoForm);
        return "confirm_delete";
    }

    /**
     * 削除処理を行う
     * @param demoForm 追加・更新用Formオブジェクト
     * @return 一覧画面の表示処理
     */
    @PostMapping(value = "/delete")
    public String delete(DemoForm demoForm){
        //指定したユーザーデータを削除
        demoService.deleteById(demoForm.getId());
        //一覧画面に遷移
        return "redirect:/to_index";
    }

    /**
     * 削除完了後に一覧画面に戻る
     * @param searchForm 検索用Formオブジェクト
     * @param model Modelオブジェクト
     * @return 一覧画面
     */
    @GetMapping("/to_index")
    public String toIndex(SearchForm searchForm, Model model){
        //一覧画面に戻り、1ページ目のリストを表示する
        searchForm.setCurrentPageNum(1);
        return movePageInList(model, searchForm);
    }

    /**
     * 削除確認画面から一覧画面に戻る
     * @param model Modelオブジェクト
     * @param searchForm 検索用Formオブジェクト
     * @return 一覧画面
     */
    @PostMapping(value = "/deleteBack")
    public String confirmDeleteBack(Model model, SearchForm searchForm){
        //一覧画面に戻る
        return movePageInList(model, searchForm);
    }

    /**
     * 追加処理を行う画面に遷移する
     * @param model Modelオブジェクト
     * @return 入力・更新画面へのパス
     */
    @PostMapping(value = "/add")
    public String add(Model model){
        model.addAttribute("demoForm", new DemoForm());
        return "input";
    }

    /**
     * 追加処理を行う画面から検索画面に戻る
     * @return 検索画面へのパス
     */
    @PostMapping(value = "/addBack")
    public String addBack(){
        return "search";
    }

    /**
     * エラーチェックを行い、エラーが無ければ確認画面に遷移し、
     * エラーがあれば入力画面のままとする
     * @param demoForm 追加・更新用Formオブジェクト
     * @param result バインド結果
     * @return 確認画面または入力画面へのパス
     */
    @PostMapping(value = "/confirm")
    public String confirm(@Validated DemoForm demoForm, BindingResult result){
        //追加・更新用Formオブジェクトのチェック処理でエラーがある場合は、
        //入力画面のままとする
        if(result.hasErrors()){
            return "input";
        }
        //エラーが無ければ確認画面に遷移する
        return "confirm";
    }

    /**
     * 一覧画面に戻る
     * @param model Modelオブジェクト
     * @param searchForm 検索用Formオブジェクト
     * @return 一覧画面の表示処理
     */
    @PostMapping(value = "/confirmBack")
    public String confirmBack(Model model, SearchForm searchForm){
        //一覧画面に戻る
        return movePageInList(model, searchForm);
    }

    /**
     * 完了画面に遷移する
     * @param demoForm 追加・更新用Formオブジェクト
     * @param result バインド結果
     * @return 完了画面
     */
    @PostMapping(value = "/send")
    public String send(@Validated DemoForm demoForm, BindingResult result){
        //チェック処理を行い、エラーがなければ、更新・追加処理を行う
        if(result.hasErrors()){
            return "input";
        }
        demoService.createOrUpdate(demoForm);
        return "redirect:/complete";
    }

    /**
     * 完了画面に遷移する
     * @param sessionStatus セッションステータス
     * @return 完了画面
     */
    @GetMapping("/complete")
    public String complete(SessionStatus sessionStatus){
        //セッションオブジェクトを破棄
        sessionStatus.setComplete();
        return "complete";
    }

    /**
     * 入力画面に戻る
     * @return 入力画面
     */
    @PostMapping(value = "/sendBack")
    public String sendBack(){
        return "input";
    }

    /**
     * 一覧画面に戻り、指定した現在ページのリストを表示する
     * @param model Modelオブジェクト
     * @param searchForm 検索用Formオブジェクト
     * @return 一覧画面の表示処理
     */
    private String movePageInList(Model model, SearchForm searchForm){
        //現在ページ数, 総ページ数を設定
        model.addAttribute("currentPageNum", searchForm.getCurrentPageNum());
        model.addAttribute("allPageNum", demoService.getAllPageNum(searchForm));
        //ページング用オブジェクトを生成し、現在ページのユーザーデータリストを取得
        Pageable pageable = demoService.getPageable(searchForm.getCurrentPageNum());
        List<DemoForm> demoFormList = demoService.demoFormList(searchForm, pageable);
        //ユーザーデータリストを更新
        model.addAttribute("demoFormList", demoFormList);
        return "list";
    }
}

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-js-submit/demo

サンプルプログラムの実行結果

下記記事の実装イメージを参照のこと。

Spring BootのWEB画面上でnull許可項目のDB更新機能を追加してみた(完成イメージと前提条件)これまで本ブログで、Spring BootのWEB画面で、MyBatisによるDB更新機能を何度か取り上げてきたが、DB更新はNull更...

要点まとめ

  • フォームと呼ばれるブロックの値を送信するSubmit処理は、JavaScriptを用いて実装することもできる。