かんがるーさんの日記

最近自分が興味をもったものを調べた時の手順等を書いています。今は Spring Boot をいじっています。

Spring Boot でログイン画面 + 一覧画面 + 登録画面の Webアプリケーションを作る ( その11 )( 登録画面作成 )

概要

Spring Boot でログイン画面 + 一覧画面 + 登録画面の Webアプリケーションを作る ( その10 )( ログイン画面作成3 ) の続きです。

  • 今回の手順で確認できるのは以下の内容です。
    • 登録画面 ( 入力→確認→完了 ) の作成、確認。ただし入力画面、確認画面までです。
    • 入力方法が <input type="text" ..... だけだったので、登録画面の Continent の入力項目をテキスト入力ではなくドロップダウンリストに変更します。

ソフトウェア一覧

参考にしたサイト

  1. Hibernate Validator - Chapter 2. Declaring and validating bean constraints
    http://docs.jboss.org/hibernate/validator/5.1/reference/en-US/html/chapter-bean-constraints.html

  2. TERASOLUNA Global Framework Development Guideline 1.0.1.RELEASE documentation - 5.5. 入力チェック
    http://terasolunaorg.github.io/guideline/1.0.1.RELEASE/ja/ArchitectureInDetail/Validation.html

  3. Tutorial: Thymeleaf + Spring - 7.5 Dropdown/List selectors
    http://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#dropdownlist-selectors

  4. HOW-TO: USING @PROPERTYSOURCE ANNOTATION IN SPRING 4 WITH JAVA 7
    http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html

  5. Reading a List from properties file and load with spring annotation @Value
    http://stackoverflow.com/questions/12576156/reading-a-list-from-properties-file-and-load-with-spring-annotation-value

    • properties ファイルに記載したカンマ区切りのデータを @Value アノテーションで List 型のフィールドにセットする方法が記載されています。
  6. m4hv-extensions Document
    http://maru.sourceforge.jp/m4hv-extensions/document.html

    • ValidationMessages.properties の日本語メッセージを作る時に参考にしました。
  7. メンテナブルCSS
    https://www.cyberagent.co.jp/corporate/techreport/report/id=7926

  8. js で利用する DOM の名前をどうやってつけたらよいのか
    http://willnet.in/78
  9. GitHub - Styleguide - CSS
    https://github.com/styleguide/css

    • 上の3つは js- プレフィックスに関してのメモです。何かで Javascript で操作するものは js- を付けて区別した方がよいという記事を見た記憶があったのですが、明確に覚えていなかったのでちょっと調べました。今作っている例だと class ではなく id に js- を付けた名称を付けてしまっていますね。。。 今度は class に付けるようにします。

手順

1.0.x-makecountryinput ブランチの作成

  1. IntelliJ IDEA 上で 1.0.x-makecountryinput ブランチを作成します。

Form クラスの作成

  1. 画面からの入力データを格納する Form クラスを作成します。src/main/java/ksbysample/webapp/basic/web の下に CountryForm.java を作成します。作成後、リンク先のその1の内容 に変更します。

CountryController クラスの修正、input.html, confirm.html の修正

  1. 今回 Continent の入力項目をテキスト入力ではなくドロップダウンリストに変更します。ドロップダウンリストに表示するリストは properties ファイルに定義してそこから取得・表示するようにしてみます。

  2. 最初に properties ファイルを作成します。 src/main/resources の下に constant.properties を作成します。作成後、リンク先の内容 に変更します。

  3. 次に定数クラスを作成します。src/main/java/ksbysample/webapp/config の下に Constant.java を作成します。作成後、リンク先の内容 に変更します。

  4. src/main/java/ksbysample/webapp/basic/web の下の CountryController.javaリンク先の内容 に変更します。

  5. src/main/resources/templates/country の下の input.html を リンク先の内容 に変更します。

  6. src/main/resources/templates/country の下の confirm.html を リンク先の内容 に変更します。

エラーメッセージの日本語化

  1. 今のままだとエラーメッセージが英語で表示されるので日本語化します。src/main/resources の下の ValidationMessages_ja_JP.properties を リンク先の内容 に変更します。

  2. src/main/java/ksbysample/webapp/basic/web の下の CountryForm.javaリンク先のその2の内容 に変更します。

動作確認

  1. 一旦この時点で動作を確認します。Gradle tasks View から bootRun タスクを実行します。

  2. ブラウザで http://localhost:8080/country/input にアクセスして登録画面を表示します。

    f:id:ksby:20150212014214p:plain

  3. 何も入力せずに「確認」ボタンをクリックします。Bean Validation が行われエラーメッセージが日本語で表示されます。

    f:id:ksby:20150212014444p:plain

  4. 今度はエラーが出ないようデータを全て入力して「確認」ボタンをクリックします。確認画面が表示されます。

    f:id:ksby:20150212014731p:plain

  5. 「戻る」ボタンをクリックします。入力画面に戻り、入力した値が表示されています。

    f:id:ksby:20150212014922p:plain

    • GovernmentForm に?が表示されているのは、全角の?を入力しているためです。エラーではありません。
    • Code2 に値が表示されていないのは入力フィールドが小さすぎるからでした。。。
  6. Ctrl+F2 を押して Tomcat を停止します。

次回は。。。

ここまで時間がかかったので一旦締めます。次回は以下の内容を実施する予定です。

  • Code2 の入力フィールドが小さすぎるのでもう少し大きくします。
  • Validator インターフェースを実装したクラスを用意して、複合項目の入力チェックも実装してみます。
  • エラー時、入力フィールドの背景色を赤にしたいのでやり方を調べます。
  • SurfaceArea と Population は @NotBlank, @Digits の2つのアノテーションを付加していますが、入力チェックは両方実行され、どちらのエラーメッセージも表示されていました。チェックの順序を指定して、1つのチェックがエラーになったら次のチェックは行わないようにする方法があるのか調べてみます。
  • 書いてある以外にもいろいろ試しているのですが、SurfaceArea の入力チェックを @NotBlank, @Digits の2つではなく @Digits だけにしても空の時にエラーになる ( @Digits だけでも必須チェックが入る? ) ことに気づきました。@Digits だけなら空の時にはエラーにならないようにして欲しいのですが、原因を調査してみます。

ソースコード

CountryForm.java

■その1

package ksbysample.webapp.basic.web;

import lombok.Data;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.Digits;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

@Data
public class CountryForm {

    @NotBlank
    @Size(max = 3, message = "{error.size.max}")
    private String code;

    @NotBlank
    @Size(max = 52, message = "{error.size.max}")
    private String name;

    @NotBlank
    @Pattern(regexp = "^(Asia|Europe|North America|Africa|Oceania|Antarctica|South America)$", message = "{countryListForm.continent.pattern}")
    private String continent;

    @NotBlank
    @Size(max = 26, message = "{error.size.max}")
    private String region;

    @NotBlank
    @Digits(integer=8, fraction=2)
    private String surfaceArea;

    @NotBlank
    @Digits(integer=11, fraction=0)
    private String population;

    @NotBlank
    @Size(max = 45, message = "{error.size.max}")
    private String localName;

    @NotBlank
    @Size(max = 45, message = "{error.size.max}")
    private String governmentForm;

    @NotBlank
    @Size(max = 2, message = "{error.size.max}")
    private String code2;

}

■その2

    @NotBlank
    @Digits(integer=8, fraction=2, message = "{error.digits.integerandfraction}")
    private String surfaceArea;

    @NotBlank
    @Digits(integer=11, fraction=0, message = "{error.digits.integeronly}")
    private String population;
  • surfaceArea の @Digists に message = "{error.digits.integerandfraction}" を追加します。
  • population の @Digists に message = "{error.digits.integeronly}" を追加します。

constant.properties

continent.list=Asia,Europe,North America,Africa,Oceania,Antarctica,South America

Constant.java

package ksbysample.webapp.basic.config;


import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@PropertySource("classpath:constant.properties")
@Getter
public class Constant {

    @Value("#{'${continent.list}'.split(',')}")
    private List<String> CONTINENT_LIST;

}
  • このクラスを使用するクラスにインジェクションして使用するので、@Component アノテーションを付加します。
  • @PropertySource アノテーションで参照する properties ファイルを指定します。ここでは constant.properties を指定します。
  • @Value アノテーションと Spring EL を使用して、設定ファイルの continent.list のデータを読み込んで List型の CONTINENT_LIST にセットします。
  • 定数クラスで読み取り専用にするので lombok の @Getter アノテーションのみ定義します。

CountryController.java

@Controller
@RequestMapping("/country")
public class CountryController {

    @Autowired
    private Constant constant;

    @RequestMapping("/input")
    public String input(CountryForm countryForm
            , Model model) {

        model.addAttribute("continentList", constant.getCONTINENT_LIST());
        return "country/input";
    }

    @RequestMapping("/input/back")
    public String inputBack(CountryForm countryForm
            , RedirectAttributes redirectAttributes) {

        redirectAttributes.addFlashAttribute("countryForm", countryForm);
        return "redirect:/country/input";
    }

    @RequestMapping("/confirm")
    public String confirm(@Validated CountryForm countryForm
            , BindingResult bindingResult
            , Model model) {

        if (bindingResult.hasErrors()) {
            model.addAttribute("continentList", constant.getCONTINENT_LIST());
            return "country/input";
        }

        return "country/confirm";
    }
  • constnat フィールドを追加します。
  • input メソッドの引数に CountryForm countryForm, Model model を追加します。Bean Validation は行わないので @Validated アノテーションは付加しません。
  • input メソッド内の処理に model.addAttribute("continentList", constant.getCONTINENT_LIST()); を追加します。
  • inputBack メソッドを追加します。確認画面で「戻る」ボタンが押された時に呼び出される処理です。
  • confirm メソッドの引数に @Validated CountryForm countryForm, BindingResult bindingResult を追加します。
  • confirm メソッドの中に Bean Validation でエラーが発生した時の処理を追加します。
  • Continent のドロップダウンリストにデータが表示されるようにするために return "country/input"; の前に必ず model.addAttribute("continentList", constant.getCONTINENT_LIST()); を呼び出すようにしているのですが、毎回呼び出すのは良い方法とは思えないので、Thymeleaf テンプレートファイル内でクラスか properties ファイルから値を取得する等して解決できないか調査中です。今回は調査しきれませんでした。。。

input.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"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>

    <title>Countryデータ登録画面(入力)</title>

    <!-- Bootstrap core CSS -->
    <link href="/css/bootstrap.min.css" rel="stylesheet"/>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="/js/html5shiv.min.js"></script>
    <script src="/js/respond.min.js"></script>
    <![endif]-->

    <!-- Custom styles for this template -->
    <style>
    <!--
    body {
        padding-top: 50px;
    }
    .navbar-brand {
        font-size: 24px;
    }
    .form-group {
        margin-bottom: 5px;
    }
    h1 {
        margin-bottom: 20px;
    }
    .cst-form-inputform {
        margin-bottom: 20px;
    }
    -->
    </style>
</head>

<body>
    <div id="header" th:include="common/header :: header (active='countryInput')"></div>

    <div class="container">
        <div class="row">
            <div class="col-sm-push-2 col-sm-10"><h1>Countryデータ登録</h1></div>
        </div>

        <div class="row">
            <div class="col-xs-12">
                <form id="countryForm" method="post" action="/country/confirm" th:action="@{/country/confirm}" th:object="${countryForm}" class="form-horizontal cst-form-inputform">
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{code}')} ? 'has-error' : ''">
                        <label for="code" class="control-label col-sm-2">Code</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-2"><input type="text" name="code" id="code" class="form-control input-sm" value="" placeholder="JPN" th:field="*{code}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{code}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{code}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{name}')} ? 'has-error' : ''">
                        <label for="name" class="control-label col-sm-2">Name</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-4"><input type="text" name="name" id="name" class="form-control input-sm" value="" placeholder="Japan" th:field="*{name}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{name}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{name}"></small></p></div></div>
                        </div>
                    </div>

                    <div class="form-group" th:classappend="${#fields.hasErrors('*{continent}')} ? 'has-error' : ''">
                        <label for="continent" class="control-label col-sm-2">Continent</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-4">
                                <select name="continent" id="continent" class="form-control input-sm" th:field="*{continent}">
                                    <option th:each="item : ${continentList}"
                                            th:value="${item}"
                                            th:text="${item}">continent</option>
                                </select>
                            </div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{continent}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{continent}"></small></p></div></div>
                        </div>
                    </div>

                    <div class="form-group" th:classappend="${#fields.hasErrors('*{region}')} ? 'has-error' : ''">
                        <label for="region" class="control-label col-sm-2">Region</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-4"><input type="text" name="region" id="region" class="form-control input-sm" value="" placeholder="Eastern Asia" th:field="*{region}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{region}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{region}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{surfaceArea}')} ? 'has-error' : ''">
                        <label for="surfaceArea" class="control-label col-sm-2">SurfaceArea</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-2"><input type="text" name="surfaceArea" id="surfaceArea" class="form-control input-sm" value="" placeholder="377829.00" th:field="*{surfaceArea}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{surfaceArea}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{surfaceArea}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{population}')} ? 'has-error' : ''">
                        <label for="population" class="control-label col-sm-2">Population</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-2"><input type="text" name="population" id="population" class="form-control input-sm" value="" placeholder="126714000" th:field="*{population}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{population}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{population}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{localName}')} ? 'has-error' : ''">
                        <label for="localName" class="control-label col-sm-2">LocalName</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-6"><input type="text" name="localName" id="localName" class="form-control input-sm" value="" placeholder="Nihon/Nippon" th:field="*{localName}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{localName}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{localName}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{governmentForm}')} ? 'has-error' : ''">
                        <label for="governmentForm" class="control-label col-sm-2">GovernmentForm</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-6"><input type="text" name="governmentForm" id="governmentForm" class="form-control input-sm" value="" placeholder="Constitutional Monarchy" th:field="*{governmentForm}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{governmentForm}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{governmentForm}"></small></p></div></div>
                        </div>
                    </div>
                    <div class="form-group" th:classappend="${#fields.hasErrors('*{code2}')} ? 'has-error' : ''">
                        <label for="code2" class="control-label col-sm-2">Code2</label>
                        <div class="col-sm-10">
                            <div class="row"><div class="col-sm-1"><input type="text" name="code2" id="code2" class="form-control input-sm" value="" placeholder="JP" th:field="*{code2}"/></div></div>
                            <div class="row" th:if="${#fields.hasErrors('*{code2}')}"><div class="col-sm-10"><p class="form-control-static text-danger"><small th:errors="*{code2}"></small></p></div></div>
                        </div>
                    </div>

                    <div class="col-xs-12"> </div>
                    <div class="text-center">
                        <button type="button" id="js-confirm" value="confirm" class="btn btn-primary">確認</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="/js/jquery.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="/js/ie10-viewport-bug-workaround.js"></script>

    <script type="text/javascript">
    <!--
    $(document).ready(function() {
        $('#code').focus();

        $('#js-confirm').bind('click', function(){
            $('#countryForm').submit();
        });
    });
    -->
    </script>
</body>
</html>
  • 確認ボタンが画面の下にピッタリくっついていることに気づいたので、少し余白を開けるために .cst-form-inputform { ... } の定義を追加します。
  • <form id="countryForm" ...>th:action="@{/country/confirm}" th:object="${countryForm}" を追加します。また class 属性を class="form-horizontal"class="form-horizontal cst-form-inputform" へ変更します。
  • 各入力項目の <div class="form-group" ...>th:classappend="${#fields.hasErrors('*{code}')} ? 'has-error' : ''" を追加します。エラー発生時に入力項目名と入力フィールドが赤くなります。
  • 各入力項目の下にエラーメッセージが表示されるよう修正します。
  • Continent の入力項目は select タグ、option タグを使用してドロップダウンリストになるよう修正します。

confirm.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"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>

    <title>Countryデータ登録画面(確認)</title>

    <!-- Bootstrap core CSS -->
    <link href="/css/bootstrap.min.css" rel="stylesheet"/>

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="/js/html5shiv.min.js"></script>
    <script src="/js/respond.min.js"></script>
    <![endif]-->

    <!-- Custom styles for this template -->
    <style>
    <!--
    body {
        padding-top: 50px;
    }
    .navbar-brand {
        font-size: 24px;
    }
    .form-group {
        margin-bottom: 5px;
    }
    h1 {
        margin-bottom: 20px;
    }
    .form-control-static {
        padding-top: 5px;
        padding-bottom: 5px;
    }
    -->
    </style>
</head>

<body>
    <div id="header" th:include="common/header :: header (active='countryInput')"></div>

    <div class="container">
        <div class="row">
            <div class="col-sm-push-2 col-sm-10"><h1>Countryデータ登録</h1></div>
        </div>

        <div class="row">
            <div class="col-xs-12">
                <form id="countryForm" method="post" action="/country/update" th:action="@{/country/update}" th:object="${countryForm}" class="form-horizontal">
                    <div class="form-group">
                        <label for="code" class="control-label col-sm-2">Code</label>
                        <div class="col-sm-2">
                            <p class="form-control-static" th:text="*{code}">JPN</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="name" class="control-label col-sm-2">Name</label>
                        <div class="col-sm-4">
                            <p class="form-control-static" th:text="*{name}">Japan</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="continent" class="control-label col-sm-2">Continent</label>
                        <div class="col-sm-4">
                            <p class="form-control-static" th:text="*{continent}">Asia</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="region" class="control-label col-sm-2">Region</label>
                        <div class="col-sm-4">
                            <p class="form-control-static" th:text="*{region}">Eastern Asia</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="surfaceArea" class="control-label col-sm-2">SurfaceArea</label>
                        <div class="col-sm-2">
                            <p class="form-control-static" th:text="*{surfaceArea}">377829.00</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="population" class="control-label col-sm-2">Population</label>
                        <div class="col-sm-2">
                            <p class="form-control-static" th:text="*{population}">126714000</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="localName" class="control-label col-sm-2">LocalName</label>
                        <div class="col-sm-6">
                            <p class="form-control-static" th:text="*{localName}">Nihon/Nippon</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="governmentForm" class="control-label col-sm-2">GovernmentForm</label>
                        <div class="col-sm-6">
                            <p class="form-control-static" th:text="*{governmentForm}">Nihon/Constitutional Monarchy</p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="code2" class="control-label col-sm-2">Code2</label>
                        <div class="col-sm-1">
                            <p class="form-control-static" th:text="*{code2}">JP</p>
                        </div>
                    </div>

                    <input type="hidden" name="code" id="code" th:value="*{code}"/>
                    <input type="hidden" name="name" id="name" th:value="*{name}"/>
                    <input type="hidden" name="continent" id="continent" th:value="*{continent}"/>
                    <input type="hidden" name="region" id="region" th:value="*{region}"/>
                    <input type="hidden" name="surfaceArea" id="surfaceArea" th:value="*{surfaceArea}"/>
                    <input type="hidden" name="population" id="population" th:value="*{population}"/>
                    <input type="hidden" name="localName" id="localName" th:value="*{localName}"/>
                    <input type="hidden" name="governmentForm" id="governmentForm" th:value="*{governmentForm}"/>
                    <input type="hidden" name="code2" id="code2" th:value="*{code2}"/>

                    <div class="col-xs-12"> </div>
                    <div class="text-center">
                        <button type="button" id="js-update" value="update" class="btn btn-primary">登録</button>
                        <button type="button" id="js-back" value="back" class="btn btn-default">戻る</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="/js/jquery.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
    <script src="/js/ie10-viewport-bug-workaround.js"></script>

    <script type="text/javascript">
    <!--
    $(document).ready(function() {
        $('#js-update').bind('click', function(){
            $('#countryForm').submit();
        });

        $('#js-back').bind('click', function(){
           $('#countryForm').attr('action', '/country/input/back');
            $('#countryForm').submit();
        });
    });
    -->
    </script>
</body>
</html>
  • .form-control-static { ... }CSS を追加します。入力画面から確認画面に遷移した時に入力値の表示位置が縦にずれるのを修正します。
  • <form id="countryForm" ...>th:action="@{/country/update}" th:object="${countryForm}" を追加します。
  • 入力値を表示する箇所に th:text="*{...}" を追加します。
  • 入力値を保持するための <input type="hidden" ... を追加します。
  • 「戻る」ボタンがクリックされたら /country/input/back を呼び出すよう $('#js-back').bind('click', function(){ ... } 内の URL を変更します。

ValidationMessages_ja_JP.properties

org.hibernate.validator.constraints.NotBlank.message=必須の入力項目です。

error.size.max = {max}文字以内で入力して下さい。
error.digits.integerandfraction = 数値を整数{integer}桁以内、小数{fraction}桁以内で入力して下さい。
error.digits.integeronly = 数値を整数{integer}桁以内で入力して下さい。

countryListForm.continent.pattern = Asia, Europe, North America, Africa, Oceania, Antarctica, South America のいずれかの文字列を入力して下さい。
  • 以下の3つを追加します。
    • org.hibernate.validator.constraints.NotBlank.message
    • error.digits.integerandfraction
    • error.digits.integeronly

履歴

2015/02/12
初版発行。