SpringBootでWebアプリ開発(バリデーション・エラーメッセージ表示①)

バリデーション入れたい箇所

  • 収入・支出の桁数(1~9999999999)
  • メモの文字数(30文字)
  • 収入/支出が未選択の時
  • カテゴリの文字数(10文字)

バリデーションの実装方法調査

実装の仕方がわからないのでまずは色々調べてみる。

Entity, Controller, Viewに手を加える必要がありそう。

Entityクラスでバリデーション実装

@Entity // This tells Hibernate to make a table out of this class
public class IncomeOutgo {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    @NotNull(message = "収入/支出を入力してください")
    @Max(value = 10, message = "収入/支出は10桁以内で入力してください")
    private Long cost;
//    @NotNull(message = "日付を入力してください")
    @DateTimeFormat
    private Date date;
    @Size(max=10, message = "MEMOは10文字以内で入力してください")
    private String memo;
    private String type;
    @NotNull(message = "カテゴリを選択してください")
    private Long category_id;

エラーメッセージの表示

IncomeOutgoController.java

  • しばらくずっとこのエラーで苦しめられた
Caused by: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'incomeOutgo' available as request attribute
  • 「「BindingResult」も「incomeOutgo」ってbean名のオブジェクトもありませんよー」と言われている
  • つまりview側のth:object="${incomeOutgo}"が機能していない

試行錯誤の末やっとできた実装はこちら。

@GetMapping("new")
public String newIncomeOutgo(IncomeOutgo incomeOutgo, Model model){
   // 中略
    return "income_outgo/new";
}

@PostMapping("new")
public String create(@ModelAttribute @Validated IncomeOutgo incomeOutgo,
                     BindingResult bindingResult,
                     Model model){
    if(bindingResult.hasErrors()){
        return newIncomeOutgo(incomeOutgo, model);
//            return "/income_outgo/new";
    }else{
        incomeOutgoService.save(incomeOutgo);
        return "redirect:/income_outgo/new";
    }
}
  • GetMappingのnewIncomeOutgoの引数にIncomeOutgo incomeOutgoを追加
  • PostMappingでエラーがあった時の戻り値をGetMappingで定義したnewIncomeOutgoに設定
  • Springのフレームワークで使えるのは、@Validではなく@Validatedの模様
    • (最初@Validと書いていたせいかエラーに苦しめられる…@Validはjavaxで使われるバリデーションみたい)

(このコントローラの仕組みをうまく説明できない…( ;∀;))

new.html

  • formタグのth:object="${incomeOutgo}"でエラーメッセージとオブジェクトをバインドさせている…?
  • th:if="${#fields.hasErrors('*{cost}')}" th:errors="*{cost}" この書き方でエラーがある時だけエラーメッセージが表示されるようになる
<h4>【支出】</h4>
<form th:action="@{/income_outgo/new}" th:method="post" th:object="${incomeOutgo}">
    <!-- 中略 -->
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">支出</label>
        <div class="col-sm-6">
            <span th:if="${#fields.hasErrors('*{cost}')}" th:errors="*{cost}"></span>
            <input type="number" class="form-control" name="cost">
        </div>
    <!-- 略 -->
  • (style適用させてないけど)メッセージが出るようになった

  • ただ、このバリデーションに対するエラーの出方に不具合が残存している
    • 11桁入力でエラーメッセージ表示→その画面のまま10桁以下を入力すると同じエラーメッセージが表示される…(原因わからず)
@NotNull(message = "収入/支出を入力してください")
@Max(value = 10, message = "収入/支出は10桁以内で入力してください")
private Long cost;
  • 画面の作りのせいで、支出の入力欄だけにエラーメッセージを出したいのに収入の入力欄にもエラーメッセージが表示されてしまう…

  • 収入/支出の入力欄をタブ切り替えにしなければ…!!

続きは次回…

SNSでもご購読できます。

コメントを残す

*