2011-01-31 79 views
11

如何在單擊按鈕時跳過JSR-303使用JSF進行Bean驗證?JSF 2.0:如何跳過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)使用直接= 「true」 和不顯示驗證錯誤

對於非確認按鈕,設置immediate = 「true」,併爲H:信息辦:

<h:messages rendered="#{param['SHOW_VALIDATION']}" /> 

然後設置保存按鈕(實際應該儘量保存表單)發送該參數:

<h:commandButton> 
    <f:param name="SHOW_VALIDATION" value="true" /> 
</h:commandButton> 

這會導致驗證發生,但僅當SHOW_VALIDATION參數存在時纔會顯示消息。

2)在小面聲明驗證有條件:

<h:inputText> 
    <f:validateRequired disabled="#{!param['VALIDATE']}" /> 
</h:inputText> 

和保存按鈕:

<h:commandButton> 
    <f:param name="VALIDATE" value="true" /> 
</h:commandButton> 

這導致字段來驗證僅當VALIDATE參數存在(=當保存按鈕已被按下)。

但這些似乎有點黑客。我如何簡單地使用JSR-303 Bean驗證,但在聲明時跳過它?

+0

那麼,我還沒有嘗試任何其他的驗證解決方案比JSR-303和JSF facelets。我認爲這個問題與JSF相關,而不是JSF-303的錯誤 - 就像他們忘記了「原生」支持在JSF中跳過驗證。似乎有很多這方面的困惑...... – 2011-01-31 16:33:47

回答

9

將您的事件處理程序設置爲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(); 
} 
... 
+0

你在實踐中如何做到這一點?你能給個例子嗎? – 2011-01-31 16:29:19

+0

要說清楚:這樣做使得JSF跳過階段3-5(處理驗證,更新模型,調用應用程序)並直接進入階段6(呈現響應)。這是可以的,因爲結果與第3階段的驗證失敗相似,JSF會跳到第6階段。如果錯誤,請糾正我。下一步就是對這個進行概括/組件化,因此不需要調用`FacesContext.getCurrentInstance()。renderResponse()`。選擇作爲接受的答案,謝謝你的好解決方案! :) – 2011-02-04 18:09:10

8

您可以禁用與標籤F中的Bean驗證: validateBean有一個屬性已禁用

例子:

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

情況: 在頁面代碼中有一個很大的輸入框。有幾個按鈕分別指向單獨的bean中的單獨操作。

爲我工作一個解決方案...

  1. 在頁面代碼:添加immediate="true"到該按鈕,併爲您希望在bean使用輸入字段的ID。
<p:inputText id="someHtmlInputId" 
       maxlength="30" 
       value="#{beanName.attr}" /> 


<p:commandButton id="someHtmlButtonId" 
        actionListener="#{beanName.doStuff}" 
        value="Button Label" 
        ajax="false" 
        immediate="true"/> 
  1. 在bean doStuff方法獲得由名稱片段病程的指標的影響,輸入名稱JSF放一些其他標識符,並將所得的參數名稱可能看起來像在此之前: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); // This is Your input parameter value waiting to be processed ;) 
}