JSF如何暂时禁用验证器以保存草稿

12

我有一个相当复杂的表单,包含许多输入和验证器。对于用户而言,完成这个表单需要相当长的时间(甚至超过一小时),因此他们希望能够保存草稿数据,即使违反了必填字段未填写等规则。

我认为这个问题在许多网络应用程序中都很常见,但是找不到任何公认的模式来实现这一点。请问如何实现?

目前我能看到以下几个选项:

  1. 在“保存草稿”按钮上使用immediate=true无法解决问题,因为UI数据将不会存储在bean中,所以我将无法访问它。从技术上讲,我可以在UI组件树中找到数据,但是遍历该树似乎不是一个好主意。
  2. 从页面中删除所有字段验证,并在表单定义的操作侦听器中以编程方式验证数据。同样不是一个好主意,表单非常复杂,有很多字段,因此通过这种方式实现的验证非常混乱。
  3. 实现自己的验证器,由某个请求属性控制,该属性将设置为标准表单提交(期望进行完整验证)并且将在“保存草稿”提交时取消设置(此时应跳过验证)。同样不是一个好的解决方案,我需要为我使用的所有验证器提供自己的包装器。

但正如您所看到的,没有一种方法是真正合理的。难道没有简单的解决方案吗?

2个回答

8

确实并不容易。在JSF生命周期中,验证非常紧密地耦合在一起。

我个人会选择选项1。虽然是些琐碎的工作,但你可以将其隐藏在一个实用类中。只需从视图根中获取相关的<h:form>,递归遍历其子元素,测试component instanceof EditableValueHolder是否为true,将找到的id-value对存储在某种类型的Map中,最后进行持久化。

第四种选择是,使用ajax技术独立保存所有数据。在此方面,jQuery很有帮助。

$.post('/savedraft', $('#formid').serialize());

这只需要客户端支持Javascript。


更新:JSF实用程序库OmniFaces有一个<o:ignoreValidationFailed>标签处理器,专门用于此目的。它确实不是一个简单的解决方案,因为它还需要一个自定义的<h:form>。 它通过在验证和更新模型值阶段提供自定义的FacesContext实例,在validationFailed()renderResponse()方法中执行NOOP来完成其工作。 因此,组件仍然被无效化,并且消息仍然被附加,但仍然会继续进行更新模型值和调用应用程序阶段。


谢谢Balus。我喜欢你的第一种选择,当数据由相位侦听器加载并重新初始化EditableValueHolders时,我应该能够做相反的事情。关于你的第二个建议,我在jQuery中找不到任何unserialize()函数,你如何加载草稿数据? - Swiety
通过在服务器端相应地设置托管bean属性。 - BalusC

1
我曾经遇到过同样的问题,但我不喜欢跳过所有验证的想法。 经过深思熟虑后,我最终只想跳过必填字段的验证。这背后的逻辑是用户要么正确地填写一个字段,要么完全不填写。这对我来说非常重要,因为所有内容最终都保存在数据库中,当然,我不希望将字符串值保存到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(),因为我想知道是否有必填字段未填写。
我在用来保存表单的实体中有一个标志(completed)。保存表单时,我检查isValidationFailed()
  • 如果true至少有一个必填字段未填写:我取消选中标志completed。(它是草稿)
  • 如果false所有表单都已完成:我选中标志completed。(它不是草稿)
这也允许我只有一个“保存”按钮,而不是两个按钮(“保存”和“另存为草稿”)。 注意事项和已知陷阱:
  • 如果您将草稿保存到数据库中,则必须确保没有 NOT NULL 约束。
  • 在使用转换器和验证器时,您必须确保它们可以处理 NULL 值。
  • 您的字段的 outputLabel 中将失去必填字段的星号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接