如果单击一个按钮,如何跳过使用JSF的JSR-303 Bean验证?
解释一些方法有点冗长的问题......考虑表格中的列表:
<h:form id="form">
<h:commandButton value="Add row">
<f:ajax execute="foo" listener="#{bean.add()}" render="foo" />
</h:commandButton>
<h:dataTable id="foo" var="foo" value="#{bean.foos}">
<h:column>
Name: <h:inputText id="field" value="#{foo.name}" required="true" />
<h:messages for="field" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" />
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
当用户单击添加或删除行时,操作应该在没有验证的情况下执行。问题是,JSF重新呈现整个列表并尝试验证它。如果存在未验证的草稿更改,则会发生验证错误,并且永远不会调用侦听器方法(因为验证失败会阻止该操作)。但是,将immediate="true"
添加到f:ajax中允许方法执行,尽管存在验证错误。但是,验证错误仍然会发生并显示在此处。
我看到两个选项:
1)使用immediate =“true”并且不显示验证错误
对于非验证按钮,设置立即=“真”,对于h:消息执行:
<h:messages rendered="#{param['SHOW_VALIDATION']}" />
然后设置保存按钮(实际应该尝试保存表单)以发送该参数:
<h:commandButton>
<f:param name="SHOW_VALIDATION" value="true" />
</h:commandButton>
这会导致验证,但除非存在SHOW_VALIDATION
参数,否则不会显示消息。
2)有条件地在facelets中声明验证:
<h:inputText>
<f:validateRequired disabled="#{!param['VALIDATE']}" />
</h:inputText>
保存按钮:
<h:commandButton>
<f:param name="VALIDATE" value="true" />
</h:commandButton>
这会导致字段仅在VALIDATE
参数存在时验证(=按下保存按钮时)。
但这些看起来很糟糕。我怎样才能简单地使用JSR-303 Bean验证,但在声明时跳过它?
答案 0 :(得分:9)
将您的事件处理程序设置为immediate=true
并在退出前调用FacesContext.renderResponse()
。
更新:
示例表单中的修改:
<h:form id="form">
<h:commandButton value="Add row">
<!-- Added immediate="true" to call bean.add() before validation phase -->
<f:ajax execute="foo" listener="#{bean.add()}" render="foo" immediate="true"/>
</h:commandButton>
<h:dataTable id="foo" var="foo" value="#{bean.foos}">
<h:column>
Name: <h:inputText id="field" value="#{foo.name}" required="true" />
<h:messages for="field" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<!-- Added immediate="true" to call bean.remove() before validation phase -->
<f:ajax execute=":form:foo" listener="#{bean.remove(foo)}" render=":form:foo" immediate="true"/>
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
bean代码中的修改:
...
public void add() {
// Your add() code
...
// Added FacesContext.renderResponse() call to skip to render response phase
FacesContext.getCurrentInstance().renderResponse();
}
...
public void remove() {
// Your remove() code
...
// Added FacesContext.renderResponse() call to skip to render response phase
FacesContext.getCurrentInstance().renderResponse();
}
...
答案 1 :(得分:8)
您可以使用 f:validateBean 标记禁用bean验证,该标记已禁用。
示例:
<h:inputText value="#{bean.name}">
<f:validateBean disabled="#{anotherBean.flag}"/>
</h:inputText>
答案 2 :(得分:2)
我们刚刚发布了针对此问题的解决方案。 详细信息如下: http://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html
简而言之,它利用了validateBean标记的binding属性。 这样做可以拦截验证方法,并根据点击的按钮决定是否让它通过。
答案 3 :(得分:-1)
情况: 在页面代码中有一个包含大量输入字段的大表单。有几个按钮,每个按钮指向单独的bean中的单独操作。
对我有用的解决方案......
immediate="true"
添加到按钮,并为您要在bean中使用的输入字段提供id。<p:inputText id="someHtmlInputId" maxlength="30" value="#{beanName.attr}" /> <p:commandButton id="someHtmlButtonId" actionListener="#{beanName.doStuff}" value="Button Label" ajax="false" immediate="true"/>
doStuff
方法中,在输入名称JSF放置一些其他标识符之前,通过名称fragment couse获取参数,结果参数名称可能如下所示:someFormId:j_idt54:someHtmlInputId Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); if (params != null) { for (String k: params.keySet()) if (k.indexOf("someHtmlInputId") != -1) params.get(k); // This is Your input parameter value waiting to be processed ;) }