Disclaimer: I'm not very experienced in coding and learned most of it by myself. There might be a very simple answer to this.
I have a html form consisting of two checkboxes (A) and (B) which submits to a spring controller. The Controller validates that both checkboxes are set. For each checkbox not set an error is set to the BindingResult. If any checkbox is not set the page is reloaded and the binding result errors are shown.
My problem: Two following submits with different boxes checked can be detected as "both have been checked".
Reproduction
First submit
- Check only one checkbox (A) of the two checkboxes
- Delete the other checkbox (B) using F12 debug editor in Chrome
- Submit
Result: Browser network analysis tab shows that only one checkbox (A) is submitted as expected. As a result in the controller the value for checkbox (A) is true and value for the missing checkbox (B) is false. So far so good.
Second submit With the following steps I get the alleged problem:
- Check the previously deleted checkbox (B)
- Delete the previously checked checkbox (A) using F12 debug editor in Chrome
- Submit
Result: In the controller now both values for the checkboxes (A) and (B) are true while I would expect only (B) to be true
Simplified Code
html form
<form th:action="@{${URL_FEEDBACK_START}}" th:field="${participant}" th:object="${participant}" method="post">
<input type="hidden" th:field="*{project}" />
<input type="checkbox" id="priceGameAccepted" th:field="*{priceGameAccepted}" class="form-check-input" required="required" />
<input type="checkbox" id="dataPrivacyAccepted" th:field="*{dataPrivacyAccepted}" class="form-check-input" required="required" />
<div class="form-group mb-0">
<div>
<button type="submit" id="submit" class="btn btn-primary">
Zum Feedback!<br /><i class="fas fa-step-forward"></i>
</button>
</div>
</div>
</form>
controller
@PostMapping(path = "/submit")
public String submit(Model model,
HttpSession session,
@ModelAttribute(SessionAttributeHelper.PROJECT) Project project,
@ModelAttribute(SessionAttributeHelper.PARTICIPANT) @Valid Participant participant,
BindingResult bindingResult) {
try {
validateOptionalPriceGameAccepted(project, participant);
validateDataPrivacyAccepted(participant);
[... here would be the following code]
} catch (DataPrivacyNotAcceptedException e) {
bindingResult.addError(new FieldError("participant", "dataPrivacyAccepted", e.getMessage()));
return backToForm(model, project);
} catch (PriceGameNotAcceptedException e) {
bindingResult.addError(new FieldError("participant", "priceGameAccepted", e.getMessage()));
return backToForm(model, project);
}
}
validation methods
private void validatePriceGameAccepted(Project project, Participant participant) throws PriceGameNotAcceptedException {
boolean priceGameStatementAccepted = participant.isPriceGameAccepted();
if(project.isPricegame() && ! priceGameStatementAccepted) {
throw new PriceGameNotAcceptedException();
}
}
private void validateDataPrivacyAccepted(@Valid Participant participant) throws DataPrivacyNotAcceptedException {
boolean dataPrivacyStatementAccepted = participant.isDataPrivacyAccepted();
if(! dataPrivacyStatementAccepted) {
throw new DataPrivacyNotAcceptedException();
}
}
software Java 11 with Spring and Thymeleaf template engine, which might be not the problem here.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
Thoughts
Is there some spring web or data feature that I don't see or understand?
Aucun commentaire:
Enregistrer un commentaire