有没有办法绕过验证并仍然更新bean值?

时间:2011-04-11 06:47:46

标签: ajax jsf java-ee richfaces

我使用Richfaces。我面临的情况是我有一个表格和2个按钮。点击其中一个按钮,比如button1,我需要验证。点击另一个,button2,我不。当我点击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"/>

Bean:w

public class bean {
.
.
.
public void actionListener(ActionEvent e) {
value = "New value";
}
.
.
.
}

2 个答案:

答案 0 :(得分:1)

在第二个按钮中将立即属性设置为 true

立即属性会跳过您的值的验证,但使用立即除了取消按钮的简单案例之外的其他任何内容都会出现问题。如果 button2 是某种取消按钮,则没有问题。

如果你需要实现比取消按钮更复杂的东西,可以在下面的文章中找到这些问题的解决方案。

How_The_Immediate_Attribute_Works

答案 1 :(得分:1)

对于这种情况,实际可以做的是编写自定义验证器并对其进行相关检查。

conditionalValidation.xhtml:

请注意h:inputHidden agregate 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;
    }

}