【发布时间】:2021-04-02 14:25:34
【问题描述】:
免责声明: 我在编码方面不是很有经验,并且大部分都是自己学习的。 这可能有一个非常简单的答案。
我有一个由两个复选框 (A) 和 (B) 组成的 html 表单,它们提交给一个弹簧控制器。控制器验证两个复选框都已设置。对于每个未设置的复选框,BindingResult 都会设置一个错误。如果未设置任何复选框,则重新加载页面并显示绑定结果错误。
我的问题:以下两个选中不同框的提交可以被检测为“都已被选中”。
复制
首次提交
- 仅选中两个复选框中的一个复选框 (A)
- 在 Chrome 中使用 F12 调试编辑器删除另一个复选框 (B)
- 提交
结果:浏览器网络分析选项卡显示只有一个复选框 (A) 按预期提交。 因此,在控制器中,复选框 (A) 的值为 true,而缺少的复选框 (B) 的值为 false。到目前为止一切顺利。
第二次提交 通过以下步骤,我得到了所谓的问题:
- 选中之前删除的复选框 (B)
- 在 Chrome 中使用 F12 调试编辑器删除之前选中的复选框 (A)
- 提交
结果:在控制器中,复选框 (A) 和 (B) 的值都为真,而我希望只有 (B) 为真
简化代码
html 表单
<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>
控制器
@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);
}
}
private String backToForm(Model model, Project project) {
UiText uiText = uts.getUiText(project, UiTextKey.MSG_FEEDBACK_START);
mfs.fillUiText(model, uiText); //mfs = ModelFillerService
mfs.fillGlobal(model);
return ApplicationPathHelper.RES_FEEDBACK_START;
}
ModelFillerService
public void fillGlobal(Model model) {
LOG.debug("Preparing model for global area");
model.addAttribute("URL_HOME", ApplicationPathHelper.URL_HOME);
model.addAttribute("URL_PROJECTHOME", ApplicationPathHelper.URL_PROJECTHOME); //TODO where necessary?
model.addAttribute("URL_IMPRESSUM", ApplicationPathHelper.URL_IMPRESSUM);
model.addAttribute("URL_DATENSCHUTZ", ApplicationPathHelper.URL_DATENSCHUTZ);
model.addAttribute("URL_PRICEGAME", ApplicationPathHelper.URL_PRICEGAME);
LOG.debug("Preparing model for feedback start area");
model.addAttribute("URL_FEEDBACK_START", ApplicationPathHelper.URL_FEEDBACK_START);
model.addAttribute("URL_FEEDBACK_QUESTION_SUBMIT", ApplicationPathHelper.URL_FEEDBACK_QUESTION_SUBMIT);
model.addAttribute("URL_FEEDBACK_RESULT_SUBMIT", ApplicationPathHelper.URL_FEEDBACK_RESULT_SUBMIT);
LOG.debug("Preparing model for anonymous area");
model.addAttribute("URL_LOGIN_FORM", ApplicationPathHelper.URL_LOGIN_FORM);
model.addAttribute("URL_LOGIN", ApplicationPathHelper.URL_LOGIN);
LOG.debug("Preparing model for administration area");
model.addAttribute("URL_ADMIN_PROJECTDETAILS", ApplicationPathHelper.URL_ADMIN_PROJECTDETAILS);
model.addAttribute("URL_ADMIN_PROJECTS", ApplicationPathHelper.URL_ADMIN_PROJECTS);
model.addAttribute("URL_ADMIN_SHOWFEEDBACK", ApplicationPathHelper.URL_ADMIN_SHOWFEEDBACK); //TODO notwendig?
model.addAttribute("URL_ADMIN_EDITUITEXT", ApplicationPathHelper.URL_ADMIN_EDITUITEXT); //TODO notwendig?
model.addAttribute("URL_ADMIN_SHOWUSERAGENTS", ApplicationPathHelper.URL_ADMIN_SHOWUSERAGENTS); //TODO notwendig?
model.addAttribute("URL_LOGOUT", ApplicationPathHelper.URL_LOGOUT);
model.addAttribute("TIMENOW", ZonedDateTimeHelper.nice(ZonedDateTimeHelper.nowCET()));
/*
* URLs for DEV profile
*/
List<String> profiles = Arrays.asList(environment.getActiveProfiles());
if (profiles.contains(ApplicationProfileHelper.DEV_PROFILE)) {
LOG.debug("Preparing model for DEV profile.");
model.addAttribute("isDevProfile", true);
}
if (profiles.contains(ApplicationProfileHelper.REV_PROFILE)) {
LOG.debug("Preparing model for REV profile.");
model.addAttribute("isRevProfile", true);
}
}
public void fillUiText(Model model, UiText uiText) {
model.addAttribute(uiText.getUiTextKey().toString(), uiText.getText());
}
验证方法
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();
}
}
软件 带有 Spring 和 Thymeleaf 模板引擎的 Java 11,这可能不是这里的问题。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
想法
是否有一些我看不到或不理解的 Spring Web 或数据功能?
【问题讨论】:
-
能否添加backToForm方法的内容?
-
@Zack 我按要求添加了代码。
标签: java html spring forms checkbox