我使用Richfaces。我面临的情况是,我有一个表单和2个按钮。在单击其中一个按钮(例如button1)时,我需要进行验证。按下另一个按钮,我就不知道了。当我单击button1并得到所有验证错误消息时,问题就出现了。这可以防止点击button2。我尝试了ajaxSingle, immediate,这有助于绕过验证,但bean值没有更新。我该怎么做呢?
代码:<h:inputSecret value="#{bean.value} redisplay="true"/>
<a4j:commandButton immediate="true" actionListener="#{bean.actionListener} reRender="ID_OF_PANEL_SURROUNDING_THIS_CODE"/>
豆:w
public class bean {
.
.
.
public void actionListener(ActionEvent e) {
value = "New value";
}
.
.
.
}
在第二个按钮中设置immediate属性为true
Immediate属性会跳过对值的验证,但是对于除取消按钮之外的任何情况使用Immediate是有问题的。如果你的button2是某种取消按钮,那就没有问题了。
如果你需要实现比取消按钮更复杂的东西,这里有一些问题的解决方案,你可以在下面的文章中找到。
How_The_Immediate_Attribute_Works
对于这种情况,实际可能做的是编写一个自定义验证器并在其中进行相关检查。
conditionalValidation.xhtml:
请注意h:inputHidden
,它聚合id并触发要调用的自定义验证器。
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="/WEB-INF/template/default.xhtml">
<ui:param name="title" value="Conditional Validation"/>
<ui:param name="bean" value="#{conditionalValidationBean}"/>
<ui:define name="content">
<a4j:form id="frmConditionalValidation">
<h:panelGrid columns="2">
<h:outputLabel for="txtValue1" value="Value 1"/>
<h:panelGroup>
<h:inputText id="txtValue1" value="#{bean.value1}"/>
<h:message for="txtValue1"/>
</h:panelGroup>
<h:outputLabel for="txtValue2" value="Value 2"/>
<h:panelGroup>
<h:inputText id="txtValue2" value="#{bean.value2}"/>
<h:message for="txtValue2"/>
</h:panelGroup>
</h:panelGrid>
<h:inputHidden id="inpDetailsProvider" required="true"
validator="#{bean.conditionalValidator}" value="1">
<f:attribute name="forceValidationBtnId" value="btnForceValidation"/>
<f:attribute name="value1InputId" value="txtValue1"/>
<f:attribute name="value2InputId" value="txtValue2"/>
</h:inputHidden>
<h:commandButton id="btnForceValidation" value="Force Validation"/>
<h:commandButton id="btnByPassValidation" value="Bypass Validation"/>
</a4j:form>
</ui:define>
</ui:composition>
ConditionalValidationBean.java
public class ConditionalValidationBean {
private String value1;
private String value2;
@SuppressWarnings("unused")
public void conditionalValidator(FacesContext context, UIComponent component, Object value) {
String forceValidationBtnId = (String) component.getAttributes().get("forceValidationBtnId");
String value1InputId = (String) component.getAttributes().get("value1InputId");
String value2InputId = (String) component.getAttributes().get("value2InputId");
UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot();
UICommand forceValidationBtn = findComponent(viewRoot, forceValidationBtnId, UICommand.class);
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
boolean forceValidation = params.containsKey(forceValidationBtn.getClientId(context));
if(forceValidation) {
UIInput value1Input = findComponent(viewRoot, value1InputId, UIInput.class);
UIInput value2Input = findComponent(viewRoot, value2InputId, UIInput.class);
String v1 = (String) value1Input.getValue();
if(v1 == null || v1.trim() == "") {
value1Input.setValid(false);
FacesMessage valueRequiredMsg = new FacesMessage("Value required");
context.addMessage(value1Input.getClientId(context), valueRequiredMsg);
}
// Rest of validation logic.
}
}
public static <T> T findComponent(UIComponent base, String id, Class<T> returnType) {
if (id.equals(base.getId())) {
return returnType.cast(base);
}
Iterator<UIComponent> children = base.getFacetsAndChildren();
while (children.hasNext()) {
T found = findComponent(children.next(), id, returnType);
if (found != null) {
return returnType.cast(found);
}
}
return null;
}
public String getValue1() {
return value1;
}
public String getValue2() {
return value2;
}
public void setValue1(String value1) {
this.value1 = value1;
}
public void setValue2(String value2) {
this.value2 = value2;
}
}