質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

2回答

4510閲覧

Thymeleafで入力フォームのバリデーションチェックを実装したい

weeno02

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

バリデーション

Validationとは特定の入力データが、求められた条件に当てまっているかをチェックするために使われます。

Thymeleaf

Thymeleaf(タイムリーフ)とは、Java用のテンプレートエンジンで、特定のフレームワークに依存せず使用することが可能です。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2021/07/21 09:40

編集2021/07/23 12:13

前提・実現したいこと

Spring Boot を用いてJavaによるウェブページ作成を行っています

Thymeleaf を用いているJavaのバリデーションチェックで、元の値をhtmlの入力フォームに表示させつつ新たに入力された値が適切かどうかを判定したいです

ファイル構成は以下の画像のようになっております(画面からは見切れていますがtemplatesフォルダ内にhtml一式が格納されています)
イメージ説明

発生している問題・エラーメッセージ

発生している問題
コンパイルエラーにはなっていないが、update.htmlにおいてUpdateForm.javaで定義したエラー条件をはじいてくれない

以下、update.htmlです(bookに書籍情報一式が格納)

html

1update.html 2<!DOCTYPE html> 3<html> 4<head> 5<meta charset="UTF-8"> 6<title>書籍を編集するよ</title> 7</head> 8<body> 9 <table> 10 <tr th:if="${validationError}" th:each="error : ${validationError}"> 11 <td style="color: red;" th:text="${error}"></td> 12 </tr> 13</table> 14 15<form th:method="POST" th:action=@{/updateResult} onSubmit="return MoveCheck()" th:object="${updateForm}"> 16書籍ID(自動入力) <p style="display:inline;" th:text="${book.bookID}"></p><br> 17<br> 18タイトル: <input type="text" th:value="${book.title}" placeholder="" th:name="title" th:id="title" > 19<br> 20著者: <input type="text" th:value="${book.writer}" placeholder="" name="writer"> 21<br> 22出版社: <input type="text" th:value="${publisher.publisherName}" placeholder="" name="publisher"> 23<br> 24価格: <input type="number" th:value="${book.price}" placeholder="" name="price"> 25<br> 26購入日: <input type="date" th:value="${book.bought}" placeholder="" name="bought" min="1900-01-01" max="2021-12-31"> 27<br> 28書籍管理部門: <input type="text" th:value="${department.deptName}" placeholder="" name="mngDept"> 29<br> 30更新日(自動入力)<p style="display:inline;" th:text="${#calendars.format(#calendars.createNowForTimeZone('Asia/Tokyo'), 'yyyy-MM-dd HH:mm:ss')}"></p><br> 31<br> 32更新者(自動入力) <p style="display:inline;" th:text="${user.name}"></p><br> 33<br> 34更新者部署(自動入力) <p style="display:inline;" th:text="${department.deptName}"></p><br> 35<br> 36 37<button type="button" onclick="history.back()">戻る</button> 38 39<input type="hidden" name="bookID" th:value="${book.bookID}"> 40<input type="hidden" name="updated" th:value="${#calendars.format(#calendars.createNowForTimeZone('Asia/Tokyo'), 'yyyy-MM-dd HH:mm:ss')}"> 41<input type="hidden" name="userName" th:value="${user.name}"> 42<input type="hidden" name="updatorDept" th:value="${department.deptName}"> 43<input type="submit" value="更新する"> 44</form> 45 46<script> 47function MoveCheck() { 48 i省略 49} 50</script> 51</body> 52</html>

html画面部の表示はこのようになっております。(一部個人情報のため伏せさせていただきますが、ご了承ください)
イメージ説明

以下、UpdateForm.javaです

Java

1字数制限のため**追記の方にまとめて記載**しました。そちらをご覧ください

MySQLの実行結果画像(一部個人情報のため伏せさせていただきますが、ご了承ください)
BOOKID:5 のように、title や writer が空欄でもはじかれずにデータベースへ登録されてしまいます

イメージ説明

試したこと

https://ti-tomo-knowledge.hatenablog.com/entry/2018/06/14/162616

を参考にinputタグの中身をいじったりもしたのですが現状うまくいっておりません

該当のソースコード

入力フォームへと遷移する

Java

1@RequestMapping(value = "/update", method = RequestMethod.POST) 2 public String update( 3 @RequestParam(name = "bookID") int bookID, 4 Model model) { 5 if(loginSessionCheck() == false) { 6 return "index"; 7 } 8model.addAttribute("updateForm", new UpdateForm()); 9 10//更新対象となる書籍情報の取得 11//ここでは省略させていただきます 12 13return "update"; //update.htmlへ 14}

入力フォームから入力完了画面へと遷移する
ここで入力フォームにエラーが確認されたら再度入力フォームへ遷移する

Java

1 2 @RequestMapping(value = "/updateResult", method = RequestMethod.POST) 3 public String updateResult( 4 @Validated 5 @RequestParam(name = "updated") Timestamp updated, 6 @RequestParam(name = "bookID") int bookID, 7 @RequestParam(name = "title") String title, 8 @RequestParam(name = "writer") String writer, 9 @RequestParam(name = "publisher") String publisher, 10 @RequestParam(name = "price") int price, 11 @RequestParam(name = "bought") Date bought, 12 @RequestParam(name = "mngDept") String mngDept, 13 @RequestParam(name = "updatorDept") String updatorDept, 14 @RequestParam(name = "userName") String userName, 15 @ModelAttribute UpdateForm updateForm, 16 BindingResult result, 17 Model model) { 18 if(loginSessionCheck() == false) { 19 return "index"; 20 } 21 //エラー内容をリストに詰めてupdate画面側に返却します 22 System.out.println("result = " + result); 23 if (result.hasErrors() == true) { 24 List<String> errorList = new ArrayList<String>(); 25 for (ObjectError error : result.getAllErrors()) { 26 errorList.add(error.getDefaultMessage()); 27 } 28 model.addAttribute("validationError", errorList); 29 return "update"; 30 } 31 32 //書籍情報の更新作業を実施 33 //ここでは省略させていただきます 34 35 return "updateResult"; 36 }

補足情報(FW/ツールのバージョンなど)

Spring Boot 2.5.2
お手数ですがご教授お願い致します。

###追記
Contoroller部分、HTML部分, JavaのForm部分を以下のように書き換えたのですがうまく動きませんでした(例外スローされてしまう)。

Controller

JAVA

1@RequestMapping(value = "/updateResult", method = RequestMethod.POST) 2 public String updateResult( 3 /*リクエストパラメタ一式を削除*/ 4 @ModelAttribute 5 @Validated UpdateForm updateForm, 6 BindingResult result, 7 Model model) { 8 if(loginSessionCheck() == false) { 9 return "index"; 10 } 11 //エラー内容をリストに詰めてupdate画面側に返却します 12 System.out.println("result = " + result); 13 if (result.hasErrors() == true) { 14 List<String> errorList = new ArrayList<String>(); 15 for (ObjectError error : result.getAllErrors()) { 16 errorList.add(error.getDefaultMessage()); 17 } 18 model.addAttribute("validationError", errorList); 19 return "update"; 20 } 21 22 /*書籍更新処理 ここでは省略させていただきます*/ 23 24 return "updateResult"; 25 }

HTML

HTML

1 2 <table> 3 <tr th:if="${validationError}" th:each="error : ${validationError}"> 4 <td style="color: red;" th:text="${error}"></td> 5 </tr> 6</table> 7 8<form th:method="POST" th:action=@{/updateResult} onSubmit="return MoveCheck()" th:object="${updateForm}"> 9書籍ID(自動入力) <p style="display:inline;" th:text="${book.bookID}"></p><br> 10<br> 11タイトル: <input type="text" th:name="title" th:id="title" th:value="${book.title}" placeholder=""> 12<br> 13著者: <input type="text" th:value="${book.writer}" placeholder="" th:name="writer" th:id="writer"> 14<br> 15出版社: <input type="text" th:value="${publisher.publisherName}" placeholder="" th:name="publisher" th:id="publisherr"> 16<br> 17価格: <input type="number" th:value="${book.price}" placeholder="" th:name="price" th:id="price"> 18<br> 19購入日: <input type="date" th:value="${book.bought}" placeholder="" th:name="bought" th:id="bought" min="1900-01-01" max="2021-12-31"> 20<br> 21書籍管理部門: <input type="text" th:value="${department.deptName}" placeholder="" th:name="mngDept" th:id="mngDept"> 22<br> 23更新日(自動入力)<p style="display:inline;" th:name="Timestamp" th:id="Timestamp" th:text="${#calendars.format(#calendars.createNowForTimeZone('Asia/Tokyo'), 'yyyy-MM-dd HH:mm:ss')}"></p><br> 24<br> 25更新者(自動入力) <p style="display:inline;" th:name="userName" th:id="userName" th:text="${user.name}"></p><br> 26<br> 27更新者部署(自動入力) <p style="display:inline;" th:name="updatorDept" th:id="tupdatorDept" th:text="${department.deptName}"></p><br> 28<br> 29 30<button type="button" onclick="history.back()">戻る</button> 31<input type="hidden" th:id="bookID" th:name="bookID" th:value="${book.bookID}"> 32 33<input type="submit" value="更新する"> 34</form> 35 36<script> 37function MoveCheck() { 38 省略 39} 40

FORM部分

JAVA

1import java.io.Serializable; 2import java.sql.Timestamp; 3import java.util.Date; 4 5import javax.validation.constraints.Min; 6import javax.validation.constraints.NotBlank; 7import javax.validation.constraints.NotEmpty; 8import javax.validation.constraints.NotNull; 9import javax.validation.constraints.Size; 10 11 12public class UpdateForm implements Serializable{ 13 14 @NotBlank(message = "タイトルを入力してね") 15 @Size(min = 1, max = 200, message = "タイトルは1文字以上200文字以内で入力してください") 16 private String title; 17 18 @NotEmpty(message = "著者を入力してね") 19 @Size(min = 1, max = 200, message = "著者は1文字以上200文字以内で入力してください") 20 private String writer; 21 22 @NotEmpty(message = "出版社を入力してね") 23 @Size(min = 1, max = 200, message = "出版社は1文字以上200文字以内で入力してください") 24 private String publisher; 25 26 @NotNull(message = "値段を入力してね") 27 @Min(value = 10, message = "{value}以上の値を設定してください") 28 private Integer price; 29 30 @NotNull(message = "購入年月日を入力してね") 31 private Date bought; 32 33 @NotEmpty(message = "管理部署を入力してね") 34 private String mngDept; 35 36 private String updatorDept; 37 38 private String userName; 39 40 private int bookID; 41 42 private Timestamp updated; 43 44 /* getter/setter は省略させていただきます */ 45}

エラー文 必要そうな部分のみ抜粋
(boughtを String から Date に変換できない、と15行目のbookIDがおかしいという指摘?)

Field error in object 'updateForm' on field 'bought': rejected value [2020-12-13]; codes [typeMismatch.updateForm.bought,typeMismatch.bought,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [updateForm.bought,bought]; arguments []; default message [bought]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'bought'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@javax.validation.constraints.NotNull java.util.Date] for value '2020-12-13'; nested exception is java.lang.IllegalArgumentException] 2021-07-23 20:57:28.304 ERROR 18044 --- [nio-8082-exec-5] org.thymeleaf.TemplateEngine  : [THYMELEAF][http-nio-8082-exec-5] Exception processing template "update": Exception evaluating SpringEL expression: "book.bookID" (template: "update" - line 15, col 39) org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "book.bookID" (template: "update" - line 15, col 39)

2つ目のエラーのbookID部分がいまいち理解できておりません・・

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2021/07/21 23:02

ThymeleafはあくまでViewテンプレートでしかないので、バリデーションはJava側の話では? サーバーサイドバリデーションですよね? この表現だとフロントサイドに見えます
weeno02

2021/07/22 04:53

仰る通り、Java側でバリデーションの記述(定義?)をしているためサーバーサイドバリデーションだと思います。 今回はHTML側で th:object="${updateForm}" などと記述するので、HTMLの記述部分にもバリデーションが機能しない原因があるかもしれないため関連ソース部分はすべて記載させていただきました。
weeno02

2021/07/22 04:55

問題として「サーバーサイドに書いたバリデーションが動作していない」ことは確かなのですが、その原因がサーバーサイドなのかフロントサイドなのかそれ以外の箇所なのかが分かりかねている状況です。
weeno02

2021/07/23 12:20

一部質問の修正を行いました。
m.ts10806

2021/07/23 12:24

バリデーションに引っ掛かった際のupdateにはUpdateFormを返してないんでは?
weeno02

2021/07/23 12:32

申し訳ございません、 当方いまいち理解できていないため説明をお願いしてもよろしいでしょうか
m.ts10806

2021/07/23 12:35

model.addAttribute("validationError", errorList); return "update"; modelにはvalidationErrorとしてerrorListしか入れてません。 updateFormもbookも渡されてません。
guest

回答2

0

updateResultの各引数はそれぞれformに存在する値でしょうか?
その場合、引数にFormを指定しておけばSpringが紐づけてくれるので、その他の値は一般的に指定しないのが普通です。

java

1public String updateResult( 2 @Validated 3 @RequestParam(name = "updated") Timestamp updated, 4 @RequestParam(name = "bookID") int bookID, 5 @RequestParam(name = "title") String title, 6 @RequestParam(name = "writer") String writer, 7 @RequestParam(name = "publisher") String publisher, 8 @RequestParam(name = "price") int price, 9 @RequestParam(name = "bought") Date bought, 10 @RequestParam(name = "mngDept") String mngDept, 11 @RequestParam(name = "updatorDept") String updatorDept, 12 @RequestParam(name = "userName") String userName, 13 @ModelAttribute UpdateForm updateForm, 14 BindingResult result, 15 Model model) {

そのため↑ではなく一般的には↓のように記述します

java

1public String updateResult( 2 @Validated @ModelAttribute UpdateForm updateForm, 3 BindingResult result, 4 Model model) {

またここの「@Validated」をFormに対してつけることで
指定したフォームのバリデーションチェックを実施するようになり
単項目チェックが有効になるかと思います。

ちなみに、バリデーションを行うのはSpring側の機能です。
Thymeleafはクライアント側の制御だけですので、できることがバリデーションエラー時に表示を変えるなどしかできません。理解の一助になれば幸いです。

投稿2021/07/22 06:17

momotuwo

総合スコア155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

weeno02

2021/07/22 22:41

ありがとうございます 確認してみます
weeno02

2021/07/23 12:16

motuwo116 様 回答を参考に書き換えていたのですが、【追記】のようなエラーが発生するようになってしまいました book.bookID" (template: "update" - line 15, col 39) というエラー内容から値の受け渡しができていない?のでしょうか
guest

0

自己解決

motuwo116様の回答に加えて、

model.addAttribute("validationError", errorList);
の前に以下のコードを追加することでほぼ期待通りの動きを実現できました

BookBean book = new BookBean();
book = bookservice.referBookInfo(bookID);//BookService.javaで定義
model.addAttribute("book", book);

//publisherName と mngDeptName と userName/Department が欲しい. PublisherBean publisher = new PublisherBean(); publisher = bookservice.getPublisherInfoFromBookBean(book); //BookService.javaで定義 model.addAttribute("publisher", publisher); DepartmentBean department = new DepartmentBean(); department = bookservice.getDepartmentInfoFromBookBean(book);//BookService.javaで定義 model.addAttribute("department", department); UserBean user = new UserBean(); user = bookservice.getUserInfoFromBookBean(book);//BookService.javaで定義 model.addAttribute("user", user);

model.addAttribute("updateForm", updateForm);

投稿2021/07/26 05:45

編集2021/07/26 05:47
weeno02

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問