问题描述
我的表单很复杂,有很多输入和验证程序.对于用户而言,完成此过程需要花费相当长的时间(甚至超过一个小时),因此他们希望能够保存草稿数据,即使该数据违反了诸如未键入必填字段的规则.
I have a pretty complex form with lots of inputs and validators. For the user it takes pretty long time (even over an hour) to complete that, so they would like to be able to save the draft data, even if it violates rules like mandatory fields being not typed in.
我相信这个问题对于许多Web应用程序来说都是常见的,但是找不到任何公认的模式应该如何实现.您能建议如何实现吗?
I believe this problem is common to many web applications, but can't find any well recognised pattern how this should be implemented. Can you please advise how to achieve that?
目前,我可以看到以下选项:
For now I can see the following options:
- 在保存草稿"按钮上使用Instant = True不起作用,因为UI数据不会存储在bean中,所以我将无法访问它.从技术上讲,我可以在UI组件树中找到数据,但是遍历似乎不是一个好主意.
- 从页面中删除所有字段验证,并在为表单定义的操作侦听器中以编程方式验证数据.再说一次,这不是一个好主意,表格真的很复杂,有很多字段,因此以这种方式实现的验证会非常混乱.
- 实现我自己的验证器,该验证器将由某个请求属性控制,该请求属性将为标准表单提交设置(预期将进行完全验证),而对于另存为草稿"提交则未设置(应跳过验证).同样,这不是一个好的解决方案,我需要为我使用的所有验证器提供自己的包装器.
- use of immediate=true on "Save draft" button doesn't work, as the UI data would not be stored on the bean, so I wouldn't be able to access it. Technically I could find the data in UI component tree, but traversing that doesn't seem to be a good idea.
- remove all the fields validation from the page and validate the data programmaticaly in the action listener defined for the form. Again, not a good idea, form is really complex, there are plenty of fields so validation implemented this way would be very messy.
- implement my own validators, that would be controlled by some request attribute, which would be set for standard form submission (with full validation expected) and would be unset for "save as draft" submission (when validation should be skipped). Again, not a good solution, I would need to provide my own wrappers for all validators I am using.
但是,正如您所见,没有人是真正合理的.真的没有简单的解决方案可以解决这个问题吗?
But as you see no one is really reasonable. Is there really no simple solution to the problem?
推荐答案
确实不是那么容易.验证与JSF生命周期紧密相关.
It's indeed not that easy. Validation is pretty tight coupled in JSF lifecycle.
我个人会选择选项1.确实是很脏的工作,但是您可以将其隐藏在实用程序类中.只需从viewroot中获取有问题的<h:form>
,递归遍历其子级,从而测试component instanceof EditableValueHolder
是否为真,将找到的id-value对存储在Map
中,最后将其持久化.
I would personally go for option 1. True, dirty work, but you can just hide that away in an utility class or so. Just grab the <h:form>
in question from the viewroot, iterate over its children recursively, hereby testing if component instanceof EditableValueHolder
is true, store the found id-value pair in sort of Map
and finally persist it.
作为第四种选择,您可以使用ajaxical powers独立保存所有数据. jQuery 对此很有帮助.
As a fourth alternative, you could save all the data independently using ajaxical powers. jQuery is helpful in this.
$.post('/savedraft', $('#formid').serialize());
它仅需要客户端的Javascript支持.
It only requires Javascript support at the client side.
更新:JSF实用程序库 OmniFaces 具有 <o:ignoreValidationFailed>
标记处理程序的确切用途.这确实不是一个简单的解决方案,因为它也需要自定义<h:form>
.它通过在验证和更新模型值阶段提供自定义的FacesContext
实例来完成其工作,该实例在validationFailed()
和renderResponse()
方法中执行NOOP.因此,这些组件仍然无效,并且消息仍然附加,但是它仍将继续进行更新模型值并调用应用程序阶段.
Update: the JSF utility library OmniFaces has a <o:ignoreValidationFailed>
taghandler for the exact purpose. It was indeed not a simple solution as it requires a custom <h:form>
as well. It does its job by providing a custom FacesContext
instance during the validations and update model values phases which does a NOOP in the validationFailed()
and renderResponse()
methods. So the components are still invalidated and the messages are still attached, but it would still proceed to the update model values and invoke application phases.
这篇关于JSF如何临时禁用验证器以保存草稿的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!