Reputation: 135
I am using Springboot and Thyemleaf, trying to validate my form data, with javax.validation.constraints
annotations.
In my template I'm using a Thyemleaf command object which is my model class Quiz
. In the model I have some fields which are validated like so -
@NotBlank(message = "Title must not be blank")
private String title;
@NotBlank(message = "Text must not be blank")
private String text;
@NotNull
@Size(min = 2, max = 6, message = "Must be at least two, no more than six options")
private List<Option> options = new ArrayList<>(); // for Thymeleaf form
Here is the HTML for input for text/title -
<form th:action="@{/create}" th:object="${quiz}" method="post">
<div class="flex-column">
<label>Title</label>
<textarea type="text" class="form-control" th:field="*{title}" rows="1"></textarea>
<div class="error" th:if="${#fields.hasErrors('title')}" th:errors="*{title}">Error</div>
</div>
<div class="flex-column">
<label>Question</label>
<textarea type="text" class="form-control" th:field="*{text}" rows="2"></textarea>
<div class="error" th:if="${#fields.hasErrors('text')}" th:errors="*{text}">Error</div>
</div>
Here is the controller for the endpoint when a form is submitted -
@RequestMapping(value = "/create", params = {"save"})
public String saveQuizFromForm(@Valid final Quiz quiz, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
for (Option option : quiz.getOptions()) {
System.out.println("Option is empty? " + option.getOption().isEmpty());
}
bindingResult.getAllErrors().forEach(System.out::println);
log.info("Binding result error: {}", quiz);
return "create";
}
log.info("Quiz form submitted: {}", quiz); // todo save quiz to db
return "welcome"; // todo return form submitted result
}
In my template I can submit the form and bindingResult
will return with a field error if title
or text
is empty and a new div is inserted with the message.
Field error in object 'quiz' on field 'text': rejected value []; codes [NotBlank.quiz.text,NotBlank.text,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [quiz.text,text]; arguments []; default message [text]]; default message [Text must not be blank]
I am encountering a problem with the field List<Option> options
. The model is annotated like so -
@Entity(name = "options_table")
public class Option {
@NotEmpty(message = "Must enter an option")
private String option;
bindingResult.getAllErrors()
does not return an error on this models field despite the input being empty, as I checked in the controller option.getOption().isEmpty()
returns true.
This is the HTML I'm using to try and display the error -
<div th:each="option, rowStat : *{options}">
<input type="text" th:field="*{options[__${rowStat.index}__].option}">
<ul th:if="${#fields.hasErrors('${quiz.options[__${rowStat.index}__].option}')}">
<li
class="error"
th:each="err :
${#fields.errors('${quiz.options[__${rowStat.index}__].option}')}"
th:text="${err}">
Input is incorrect
</li>
</ul>
</div>
I have also tried
th:if="${#fields.hasErrors('*{options[__${rowStat.index}__].option}')}"
th:each="err : ${#fields.errors('*{options[__${rowStat.index}__].option}')}"
I am getting no exceptions, but no error li
are created either.
I have checked this very similar question here but it has not fixed the problem.
I have the Spring Boot starter validation dependency in my build.gradle file.
implementation 'org.springframework.boot:spring-boot-starter-validation'
Upvotes: 0
Views: 1143
Reputation: 135
I added @Valid
annotation to the field in model Quiz
. This recursively checks for validated objects and fixed my mistake.
@NotNull
@OneToMany(mappedBy = "quiz", cascade = CascadeType.ALL)
@JsonManagedReference
@Valid
@Size(min = 2, max = 6, message = "Must be at least two, no more than six options")
private List<Option> options = new ArrayList<>();
Upvotes: 1