首页 文章

JSF 2.0:如何跳过JSR-303 bean验证?

提问于
浏览
12

当点击一个按钮时,如何跳过使用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”并且不显示验证错误

对于非验证按钮,设置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验证,但在声明时跳过它?

4 回答

  • 2

    将事件处理程序设置为 immediate=true 并在退出之前调用 FacesContext.renderResponse() .

    UPDATE

    示例表单中的修改:

    <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

    您可以使用具有属性 disabled 的标记 f:validateBean 禁用bean验证 .

    例:

    <h:inputText value="#{bean.name}">
       <f:validateBean disabled="#{anotherBean.flag}"/>
    </h:inputText>
    
  • 9

    我们刚刚发布了针对此问题的解决方案 . 详细信息如下:http://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html

    简而言之,它利用了validateBean标记的绑定属性 . 这样做可以拦截验证方法,并根据单击的按钮决定是否让它通过 .

  • 8

    情况:在页面代码中有一个包含大量输入字段的大表单 . 有几个按钮,每个按钮指向单独的bean中的单独操作 .

    一个对我有用的解决方案......

    • 在页面代码中:将 immediate="true" 添加到按钮,并为要在bean中使用的输入字段提供id .

    <p:inputText id =“someHtmlInputId”
    MAXLENGTH = “30”
    value =“#
    ”/>

    <p:commandButton id =“someHtmlButtonId”
    的ActionListener = “#

    value =“按钮标签”
    AJAX = “假”
    立即= “真”/>

    • 在bean 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); //这是等待处理的输入参数值;)
    }

相关问题