validation - 当用户想要覆盖时,JSF 表单验证跳过特定验证器以进行第二次提交
问题描述
我正在使用两个验证器验证用户输入的帐号,一个用于基本标准格式,另一个用于根据存储在数据库中的值验证帐号。有效帐号的数据库可能并不总是最新的,所以我想允许用户覆盖并提交他们输入的帐号,但前提是数据库验证失败。我总是想验证它的标准格式 8 个字符,没有空格。
<h:form id="formId">
<p:panelGrid>
<p:row>
<p:column>
<p:outputLabel value="Account : " for="acct" />
</p:column>
<p:column>
<p:selectOneMenu id="acct" value="#{bean.acct.acctNum}" effect="fold" editable="true" validator="acctLengthAndSpaceValidator" required="true" requiredMessage="Required">
<f:selectItems value="#{bean.mySavedAccounts}" var="acct"
itemLabel="#{acct.acctNumber} itemValue="#{acct.acctNumber}" />
<o:validator validatorId="accountDatabaseValidator" disabled="#{bean.skipDbValidation}" />
</p:selectOneMenu>
</p:column>
<p:column>
<p:messages for="acct" showDetail="true" skipDetailIfEqualsSummary="true" />
</p:column>
</p:row>
</p:panelGrid>
<br />
<p:selectBooleanCheckbox rendered="#{facesContext.validationFailed}" value="#{bean.skipDbValidation}" itemLabel="I know this account is really valid, please skip validation and let me submit!">
<p:ajax update="@this" listener="#{bean.testListener()}" />
</p:selectBooleanCheckbox>
<p:commandButton value="Submit" action="#{bean.submit()}" update="formId"/>
</h:form>
该复选框在最初提交表单并出现任何验证失败后出现(我将弄清楚如何隔离到失败的 accountDatabaseValidator)。但是当我选择复选框并再次提交时,两个验证器仍然被触发。我添加了 ajax 侦听器进行调试,它没有触发,布尔值skipDbValidation
仍然为 false。
也许我的方法在实现我对数据库进行验证的具体目标方面是不正确的,但随后让用户选择在初始失败后跳过数据库验证。
编辑
如果我rendered="#{facesContext.validationFailed}"
从复选框中删除并让它一直可见,skipDbValidation
如果复选框被选中,则布尔值将设置为 true,然后在后续提交时,skipDbValidation
按预期忽略。但我不希望允许用户首先绕过可见的复选框。只有在验证失败后。
解决方案
这不起作用的技术解释是rendered
在处理表单提交期间重新评估该属性。此时,faces 上下文validationFailed
不再存在(仅validationFailed
在上一个请求期间),因此组件不再呈现,然后组件的提交值将不会被应用。这匹配 #6 的commandButton/commandLink/ajax action/listener method not invoked 或 input value not set/updated。
通过在客户端而不是服务器端呈现它来解决您的工作是可以接受的。但我认为您只想在调用特定验证器时才显示它。至少有两种方法可以实现这一点:
检查
UIInput#isValid()
感兴趣的输入组件。您可以通过组件的binding
属性将组件绑定到视图(而不是 bean!)来实现这一点,这样您就可以在同一视图的其他地方引用它。<p:selectOneMenu binding="#{acct}" ...> ... </p:selectOneMenu> ... <p:selectBooleanCheckbox styleClass="#{acct.valid ? 'ui-helper-hidden' : ''}" ...> ... </p:selectBooleanCheckbox>
请注意,我借此机会重用了 PrimeFaces 提供的样式类。
或者,使验证器成为视图范围的 bean,并
<o:validator binding>
改为通过引用它。@Named @ViewScoped public class AccountDatabaseValidator implements Validator, Serializable { private boolean validationFailed; @Override public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { // ... validationFailed = !isValid(value); if (validationFailed) { throw new ValidatorException(createError("Invalid value")); } } public boolean isValidationFailed() { return validationFailed; } }
<p:selectOneMenu ...> <o:validator binding="#{accountDatabaseValidator}" ... /> </p:selectOneMenu> ... <p:selectBooleanCheckbox rendered="#{accountDatabaseValidator.validationFailed}" ...> ... </p:selectBooleanCheckbox>
推荐阅读
- odoo - odoo:不可能在 one2many 上使一条线不可见吗?
- unhandled-exception - Visual Studio 2017 中未处理的异常:内存位置 0x0023F6A0 处的 unsigned long
- python - 编写 if-else 循环以根据条件填充数据框列时出现 ValueError
- python-3.x - 如何计算 netcdf 文件中的加权平均值
- windows - 为什么使用通配符在 Windows 命令行中重命名文件时字符会消失?
- java - 如何在 redisson 中的多个 JVM 之间同步本地缓存(RLocalCachedMap 实例)?
- apache-flink - Flink 功能扩展 ListCheckpointed 不会从检查点恢复
- python - 在某一点应用过滤器
- go - go中带有互斥锁的竞争条件以及在哪里嵌入锁、父结构或子结构?
- javascript - 如何流式输入'require('')'图像?