任何绕过验证并仍然更新bean值的方法



我使用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;
    }
}

最新更新