JSF如何临时禁用验证器以保存草稿
我有一个非常复杂的表单,有很多输入和验证器。对于用户来说,这需要相当长的时间(甚至超过一个小时)才能完成,因此他们希望能够保存草稿数据,即使它违反了规则,如未键入必填字段 我相信这个问题在许多web应用程序中都很常见,但找不到任何公认的模式来实现它。你能告诉我如何做到这一点吗 目前,我可以看到以下选项:JSF如何临时禁用验证器以保存草稿,jsf,validation,Jsf,Validation,我有一个非常复杂的表单,有很多输入和验证器。对于用户来说,这需要相当长的时间(甚至超过一个小时)才能完成,因此他们希望能够保存草稿数据,即使它违反了规则,如未键入必填字段 我相信这个问题在许多web应用程序中都很常见,但找不到任何公认的模式来实现它。你能告诉我如何做到这一点吗 目前,我可以看到以下选项: 在“保存草稿”按钮上使用immediate=true不起作用,因为UI数据不会存储在bean上,所以我无法访问它。从技术上讲,我可以在UI组件树中找到数据,但遍历它似乎不是一个好主意。 从
但正如你所见,没有人是真正理性的。这个问题真的没有简单的解决办法吗?确实没有那么容易。验证在JSF生命周期中是紧密耦合的 我个人会选择选项1。没错,这是一项肮脏的工作,但您可以将其隐藏在实用程序类中。只需从viewroot中抓取有问题的
,递归地迭代其子级,从而测试EditableValueHolder的组件实例是否为true,将找到的id值对存储在映射的排序中,最后将其持久化
作为第四种选择,您可以使用ajaxical Power独立保存所有数据。在这方面很有帮助
$.post('/savedraft', $('#formid').serialize());
它只需要客户端的Javascript支持
更新:JSF实用程序库有一个标记处理程序,用于确切的用途。这确实不是一个简单的解决方案,因为它还需要一个定制的
。它通过在验证和更新模型值阶段提供一个自定义的FacesContext
实例来完成其工作,该实例在validationFailed()
和renderResponse()方法中执行NOOP。因此组件仍然是无效的,消息仍然是附加的,但它仍然会进入更新模型值和调用应用程序阶段。我也有同样的问题,我不喜欢跳过所有验证的想法。经过深思熟虑,我最终只想跳过必填字段验证。这背后的逻辑是用户要么正确地填写字段,要么根本不填写。这对我来说非常重要,因为所有内容最终都在数据库中,当然,我不希望数据库字段溢出,或者最终将String
值保存到INT
数据库字段中
根据我的经验,跳过必填字段允许有足够的机动余地来保存草稿。为了实现这一点,我最终编写了一个显示单个警告消息的requiredWarnValidator
public void validate(FacesContext context, UIComponent component, Object value)
throws ValidatorException {
if (value == null) {
FacesMessage message = new FacesMessage();
message.setSeverity(FacesMessage.SEVERITY_WARN);
message.setSummary("This field is required.");
context.addMessage(component.getClientId(), message);
context.validationFailed();
}
}
在这个验证器中,我不会抛出一个ValidatorException()
,因为我想通过验证阶段,但我调用validationFailed()
,因为我想知道是否有必填字段没有填写
我在用于保存表单的实体中有一个标志(已完成
)。保存表单时,我选中了isValidationFailed()
- 如果
true
至少有一个必填字段未填写:我取消选中标志completed
。(这是一份草稿)
- 如果
false
所有表单都已完成:我检查标志completed
。(这不是草案)
这也允许我有一个“保存”按钮,而不是两个按钮(“保存”和“另存为草稿”)
注意事项和已知陷阱:
- 如果要将草稿保存到数据库,则必须确保没有
notnull
约束
- 使用转换器和验证器时,必须确保它们能够处理
NULL
值李>
- 您将丢失字段的
outputLabel
中所需的字段星号
谢谢你,巴卢斯。我喜欢您对选项1的想法,当同相侦听器加载数据并重新初始化EditableValueHolders时,我可能会做相反的事情。关于您的第二个建议,我在jQuery中找不到任何unserialize()函数,您将如何加载草稿数据?通过在服务器端相应地设置托管bean属性。