48

我有多个表格,其中有必填字段和可选字段。

提交这样的表单,我需要对要执行的 required-attribute 进行验证,这可以正常工作。要取消immediate="true"这样的表单,我使用上的属性p:commandbutton,这使得它的操作在应用请求值阶段发生,如下所述:如何在单击特定按钮时跳过验证?

但是,对于大型表单,我想为用户提供一个保存按钮,以便他可以稍后继续。

为了仅保存当前状态,我还想忽略所需属性的验证。但是,使用immediate="true"不起作用,因为那时我的简单保存方法什么也没保存,因为 JSF 生命周期从未达到“UpdateModelValues”阶段。(根据http://www.javacodegeeks.com/2012/01/jsf-and-immediate-attribute-command.html

那么,如何绕过 required-check 但不跳过一半的生命周期呢?

4

6 回答 6

74

只要是表单的成员,每个 Button 都会在 Param-List 中创建一个条目。所以我简单地对“必需”参数应用了该条目是否存在的检查:

<h:form id="form" prependId="true">
...
<p:inputText id="someId"
    required="#{param['form:save']==null}" ... />
...
<p:commandButton id="save" value="Save" />
<p:commandButton id="submit" value="Submit" />
<p:commandButton id="cancel" value="Cancel" immediate="true" />
</h:form>

当我单击“提交”时param['form:save']is NULL,然后将表达式转换true为执行验证。

当我单击“保存”时param['form:save']NOT NULL但为空!),它解析为false因此忽略验证。(或者假设 JSF 认为它不是必填字段,因为表达式 beeing 被评估为false

于 2013-01-15T10:43:04.533 回答
5

这是一个很好的问题,也是一个非常有用的答案。这种方法省去了很多麻烦immediate="true"

我想添加此信息(但还不允许发表评论)。您的代码示例似乎需要JSF 2.0或更高版本(纠正我)。如果您像我一样该死地使用 JSF 1.1/1.2,那么请考虑以下更改/添加:

<h:form id="form">
...
<p:inputText id="someId" required="#{!empty param['save']}" ... />
...
<p:commandButton id="save" value="Save" />
</h:form>
  • JSF 1.1 中没有属性 prependId
  • 因此在 param[...] 你必须只指定按钮 id
  • 您使用的语法="{true and ...}"可能是错误的(否#)?
  • 正如您从您自己的编辑历史中看到的那样,“null or not null”逻辑不是很直观:) 这就是为什么!empty ...当我偶然发现它时我立即喜欢它的原因。
于 2014-01-29T16:48:37.527 回答
5

如果您想在单击按钮时跳过验证,则可以轻松地将参数添加到要跳过它的按钮。例子:

<p:commandButton value="button1" action="#{bean.action()}" >
   <f:param name="skipValidator" value="true"/>
</p:commandButton>

然后在验证器中您可以读取此参数,如果为真则跳过它:

@FacesValidator("com.validators.MyValidator")
public class MyValidator implements Validator{

  public void validate(FacesContext ct, UIComponent co, Object obj) throws ValidatorException { 
    if(!continueValidation()){
      return;
    }
    // validation process
  }

protected boolean continueValidation() {
    String skipValidator= FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("skipValidator");
    if (skipValidator != null && skipValidator.equalsIgnoreCase("true")) {
      return false;
    }
    return true;
  } 
}
于 2015-02-12T08:41:56.740 回答
1

其他人建议的替代方法是使用自定义BeanValidator来验证表单,如果说,单击带有 id 保存的按钮。任何其他未隐式定义为执行验证的按钮都不会验证,而只是提交可用的数据。在这里找到完整的干净的例子

于 2016-05-03T12:52:36.667 回答
1

对于这种情况,我使用skipValidators (假设所有验证都被跳过)。来自omnifaces的代码

<h:form>
  <h:dataTable value="#{bean.items}" var="item">
    <h:column>
        <h:inputText value="#{item.value}" required="true" />
    </h:column>
  </h:dataTable>
  <h:commandButton value="add new row" action="#{bean.add}">
    <o:skipValidators />
  </h:commandButton>
  <h:commandButton value="save all data" action="#{bean.save}" />
  <h:messages />
</h:form>
于 2019-01-04T10:31:04.933 回答
0

就我而言,我没有在参数中找到按钮的 clientId,但我 param['javax.faces.source'] = buttonClientId在 requestmap 中找到了它。该值将是单击按钮的 clientId。

于 2014-12-22T15:29:04.747 回答