【Java・SpringBoot・Thymeleaf】エラーメッセージを個別に表示（SpringBootアプリケーション実践編6）

ログインをして、ユーザー一覧を表示するアプリケーションを作成し、
Springでの開発について勉強していきます🌟
前回の日本語でのエラー表示に引き続き**エラーメッセージを個別に表示する実装**をします

前回の記事🌟
[【Java・SpringBoot・Thymeleaf】日本語でエラーを表示（SpringBootアプリケーション実践編5）
](https://qiita.com/suema0331/items/a76817e28de9baaac2d8)


##エラーメッセージを個別に表示
* htmlファイルを修正して、エラーの場合だけCSSを変更して、テキストボックスを赤くします

###エラー用CSSの追加
* **th:classappend属性**でCSSのclassを追加する

```html
<div class="form-group" th:classappend="${#fields.hasErrors('userId')} ? 'has-error'">
```
* エラー時だけclass属性にhaserrorを追加
* haserrorはBootstrapのclassで、テキストボックスの枠を赤くする
    * **`${#fields.hasErrors('<フィールド名>')}?'haserror'`**で、trueかfalseかを判定
    * trueの場合のみhaserror classを追加
  

###個別エラーメッセージの表示
* **th:if属性**に条件式を設定
    * trueの場合のみ、そのタグが表示される
* **`th:if="${#fields.hasErrors('<フィールド名>')}" th:errors="∗{<フィールド名>}"`**

```html
<span class="text-danger" 
    th:if="${#fields.hasErrors('userId')}" 
    th:errors="*{userId}"> userId error 
</span>
```
* 上の例では、th:if属性でフィールドの**バリデーションでエラーがあるとtrue**を返し、th:errors属性で各フィールドのエラーメッセージを表示する


```signup.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"></meta>

    <!-- Bootstrapの設定 -->
    <link th:href="@{/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css}" rel="stylesheet"></link>
    <script th:src="@{/webjars/jquery/1.11.1/jquery.min.js}"></script>
    <script th:src="@{/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js}"></script>

    <title>SignUp</title>
</head>
<body>
<div class="col-sm-5">
    <div class="page-header">
        <h1>ユーザー登録画面</h1>
    </div>
    <form method="post" th:action="@{/signup}" th:object="${signupForm}">
        <table class="table table-bordered table-hover">
            <!-- ユーザーIDの入力エリア -->
            <tr>
                <th class="active col-sm-3">ユーザID</th>
                <td>
                    <!--エラー用CSSの追加-->
                    <div class="form-group"
                         th:classappend="${#fields.hasErrors('userId')} ? 'has-error'">
                        <input type="text" class="form-control"
                               th:field="*{userId}" />
                        <!--個別エラーメッセージ表示-->
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('userId')}"
                              th:errors="*{userId}">
                                userId error
                            </span>
                    </div>
                </td>
            </tr>
            <!-- パスワードの入力エリア -->
            <tr>
                <th class="active">パスワード</th>
                <td>
                    <div class="form-group"
                         th:classappend="${#fields.hasErrors('password')} ? 'has-error'">
                        <input type="text" class="form-control"
                               th:field="*{password}" />
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('password')}"
                              th:errors="*{password}">
                                password error
                            </span>
                    </div>
                </td>
            </tr>
            <!-- ユーザー名の入力エリア -->
            <tr>
                <th class="active">ユーザー名</th>
                <td>
                    <div class="form-group"
                         th:classappend="${#fields.hasErrors('userName')} ? 'has-error'">
                        <input type="text" class="form-control"
                               th:field="*{userName}" />
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('userName')}"
                              th:errors="*{userName}">
                                userName error
                            </span>
                    </div>
                </td>
            </tr>
            <!-- 誕生日の入力エリア -->
            <tr>
                <th class="active">誕生日</th>
                <td>
                    <div class="form-group"
                         th:classappend="${#fields.hasErrors('birthday')} ? 'has-error'">
                        <input type="text" class="form-control" placeholder="yyyy/MM/dd"
                               th:field="*{birthday}"/>
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('birthday')}"
                              th:errors="*{birthday}">
                                birthday error
                            </span>
                    </div>
                </td>
            </tr>
            <!-- 年齢の入力エリア -->
            <tr>
                <th class="active">年齢</th>
                <td>
                    <div class="form-group"
                         th:classappend="${#fields.hasErrors('age')} ? 'has-error'">
                        <input type="text" class="form-control"
                               th:field="*{age}" />
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('age')}"
                              th:errors="*{age}">
                                age error
                            </span>
                    </div>
                </td>
            </tr>
            <!-- 結婚ステータスの入力エリア -->
            <tr>
                <th class="active">結婚</th>
                <td>
                    <div class="form-group">
                        <div th:each="item : ${radioMarriage}">
                            <input type="radio" name="radioMarrige"
                                   th:text="${item.key}"
                                   th:value="${item.value}"
                                   th:field="*{marriage}">
                            </input>
                        </div>
                        <span class="text-danger"
                              th:if="${#fields.hasErrors('marriage')}"
                              th:errors="*{marriage}">
                                marriage error
                            </span>
                    </div>
                </td>
            </tr>
        </table>
        <!-- エラーメッセージの一覧表示 -->
        <ul>
            <li th:each="error : ${#fields.detailedErrors()}">
                <span th:text="${error.message}">Error message</span>
            </li>
        </ul>
        <!-- ユーザー登録ボタン -->
        <button class="btn btn-primary" type="submit">ユーザー登録</button>
    </form>
</div>
</body>
</html>
```

#SpringBootを起動し、ユーザー登録画面を確認！
* http://localhost:8080/signup
* ユーザー登録画面で、何も入力せずにユーザー登録ボタンをクリック
* 入力項目毎にエラーメッセージを表示することができました〜〜〜p(^_^)q
* このままでは、**バリデーションのチェックが全て同時**に実行されていて、パスワードに何も入力してないのにエラーメッセージが複数表示されてしまっている。。。
* 次回はバリデーションチェックの順番を設定します^^

![個別エラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282755/e196620a-5044-f52c-cd3c-385e8447b190.png)