如何让验证依赖于按下的按钮?

37
我已经创建了一个表单,希望在新建项时在表格中显示以前存在的项。当填写表单时,我想显示匹配的项。但是,当我尝试在表单未完成时过滤列表时,会出现验证消息,并且表格不会更新。
不知道是否可能,但我想做类似这样的事情:
<h:form id="form">

    <h:outputText value="Name: "/>
    <p:inputText value="#{itemsBean.name}" id="name" required="true"/>
    <br/>
    <h:outputText value="Description: "/>
    <p:inputText value="#{itemsBean.description}" id="description" required="true"/>

    <p:commandButton value="Save" update="form" actionListener="#{itemsBean.save}"/> //validate and save
    <p:commandButton value="Filter" update="form" actionListener="#{itemsBean.updateItemsList}"/> //don't validate, and update the table.

    <p:dataTable id="list" value="#{itemsBean.itemsList}" var="item">     
        <p:column>
            <h:outputText value="#{item.name}"/>
        </p:column>
        <p:column>
            <h:outputText value="#{item.description}"/>
        </p:column>
    </p:dataTable>

</h:form>

我对JSF非常陌生。


"wan't"........ - Andrew
4个回答

67
我理解你想要基于name输入字段进行过滤。 <p:commandButton>默认发送ajax请求,并具有process属性,您可以在提交期间指定要处理哪些组件。 在您的情况下,您应该仅处理name输入字段和当前按钮(以便调用其操作)。
<p:commandButton process="@this name" ... />
< p > process属性可以接受由(相对)客户端组件的ID(空格分隔)构成的集合,其中@this指代当前组件。在<p:commandButton>的情况下,它的默认值为@form(覆盖了当前表单和被按下的按钮的所有输入字段),这就是为什么在您最初的尝试中它们都被验证过的原因。在上面的示例中,所有其他输入字段都不会被处理(因此也不会被验证)。

然而,如果您打算在按下相关按钮时跳过所有字段的required验证,以便最终处理多个不必须填写所有字段的字段,则需要将required="true"变成一个条件,检查按钮是否已经被按下。例如,只有当保存按钮被按下时才使其为true

<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:inputText ... required="#{not empty param[save.clientId]}" />
...
<p:commandButton binding="#{save}" value="Save" ... />

这样当按下不同的按钮时,它就不会被验证为 required="true"。上述示例中的技巧在于已发送了按下按钮的名称(即客户端ID)作为请求参数,并且您只需检查其是否存在于请求参数映射中。

另请参见:


4
能否提供一个更详细的例子来说明save元素应该从哪里得到?它是一个bean吗?而clientId是一个参数吗? 就像我之前所说,我对Java和JSF都很陌生,并且一直在学习。但我还是不知道自己是否在问一些太基础的问题。 非常感谢您抽出时间来回答。 - Roteke
2
不,示例是原样的。 #{save} 绑定到视图上。 clientId 只是它的属性。另请参阅 http://docs.oracle.com/javaee/6/api/javax/faces/component/UIComponent.html#getClientId%28%29。除非您想从 bean 内部操作组件,否则无需将其绑定到 bean 属性。但是,如果您不需要,则在 bean 中没有未使用的属性。另请参阅 https://dev59.com/tmsz5IYBdhLWcg3wADS6 - BalusC
1
为什么我们不能像以前那样在PrimeFaces中使用经典的立即属性? - Ondrej Bozek
@BalusC,您将我的问题标记为此问题的重复。我有两个<h:comandbutton><f:ajax execute =“@ form”render =“@ none”/>(这与默认的<p:commandButton>完全相同,不是吗?)。 它可以在没有<f:ajax>的情况下工作,但不能使用...您可以查看一下。 也许我太瞎了? - alexander
@Alexander:如果您使用prependId="false"或嵌套表单(这在您的问题中看不到),它将以这种方式失败。只需永远不要使用prependId并且不要嵌套表单即可。 - BalusC
显示剩余9条评论

9

我已经测试过非ajax提交:

<p:inputText ... required="#{not empty param.includeInSave1}" />
...
<p:inputText ... required="true" />
...
<p:commandButton value="Save1" ajax="false">
  <f:param name="includeInSave1" value="true" />
</p:commandButton>

<p:commandButton value="Save2" ajax="false" />

第一个输入框仅在点击“保存1”按钮时进行必填验证。

这个可以被绕过。你最好检查JSF视图状态中是否存在某些内容,而不是任意和完全由客户端控制的请求参数。请参见当前接受的答案。 - BalusC

7
除了BalusC答案(非常有用和完整),我想补充一点,当你使用<h:commandButton />时,它将验证(必填项、自定义验证)位于命令按钮所在的<h:form />中的所有字段,因此当您需要使用多个命令按钮时,考虑使用不同的<h:form />来承担不同的职责,以避免命令按钮提交操作中的意外行为。BalusC在一个回答中对这点进行了很好的解释:在JSF页面中使用多个h:form 如果您的表单具有验证,但您没有更新<h:form />或没有显示消息,则可能会认为<h:commandButton />未触发您的操作,但很可能是未显示的验证问题。

2
将您的筛选命令按钮更改为以下内容,以忽略验证:
<p:commandButton value="Filter" update="list" actionListener="#{itemsBean.updateItemsList}" process="@this"/>

编辑:

在SO上找到了相关帖子,我认为这也可以解决你的问题。

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


1
这种方式可以绕过验证,但是表单值为空传递到itemsBean,过滤操作无法进行。谢谢您的快速回复。 - Roteke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接