2011-01-31 8 views
11

ボタンをクリックしたときにJSFを使用してJSR-303 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に追加すると、検証エラーが発生してもメソッドを実行することができます。ただし、引き続き検証エラーが発生し、ここに表示されます。

私は2つのオプションを参照してください。

1)=「true」を即時使用し、検証エラーに非検証ボタンの

を示していない、=「真」と時間即時設定:メッセージが行います。その後

<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パラメータが存在する場合にのみ、検証するフィールドを起こし(=たら、Saveボタン押されている)。

しかし、これらはハックのように思えます。単純にJSR-303 Bean検証を使用することはできますが、宣言されている場合はスキップしますか?

+0

まあ、私はJSR-303やfaceletsとJSF以外の検証ソリューションを試していません。私はこの問題がJSF関連であり、JSF-303の誤りではないと思います。JSFで検証をスキップすることを「ネイティブに」忘れていたようです。この周りに多くの混乱があるようです... –

答えて

9

イベントハンドラをimmediate=trueに設定し、終了する前にFacesContext.renderResponse()を呼び出します。

UPDATE:あなたの例の形で

変更:あなたのBeanコードで

<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> 

変更:

... 
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

実際にそれをどうやってやっていますか?あなたは例を挙げることができますか? –

+0

これを行うと、JSFはフェーズ番号3〜5をスキップします(プロセスの検証、モデルの更新、アプリケーションの起動)。フェーズ6(レンダリングの応答)に直接進みます。これはOKです。その結果は、フェーズ3で検証が失敗し、JSFがフェーズ6にスキップする場合とまったく同じです。間違っていれば私を修正してください。次のステップはこれを一般化/コンポーネント化することで、 'FacesContext.getCurrentInstance()。renderResponse()'は必要ないでしょう。受け入れられた答えとしてピッキングすると、素晴らしいソリューションに感謝します! :) –

+1

私は上記を試して、一般的にはうまく動作します。私の場合は次のとおりです - 私はコマンドボタンを使用して、ページにいくつかのテキストボックスを動的に追加します。 'immediate =" false "'を使用すると、ページの検証によって更新が妨げられ、表示されなくなります。 'immediate =" true "'を使用し、AJAXリクエストを行う前にいくつかの入力値を変更すると、変更はサブミットされません。任意のアイデアコールバックで入力データを変更して読み込むことと、検証を同時にトリガしないことの両方を達成するにはどうすればよいですか?事前に感謝 –

8

あなたがタグFと豆の検証を無効にすることができます。属性がであるvalidateBeanが無効にされました

例:私たちはこの問題の解決策を公開している

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

これも良い情報です。しかし、フォームの各フィールドにこれを設定するのはやや面倒です... –

+2

ここに示すように、複数の入力コンポーネントを 'f:validateBean'でもラップすることができます:http://stackoverflow.com/a/17503608/ 1725096 –

-1

状況: ページコードには、多くの入力フィールドを持つ大きなフォームがあります。別々のBean内で別々のアクションを指すボタンがいくつかあります。

私のために働いたソリューション...ページコードで

  1. :ボタンにimmediate="true"を追加し、あなたが豆で使用する入力フィールドのidを提供しています。豆doStuff方法で
<p:inputText id="someHtmlInputId" 
       maxlength="30" 
       value="#{beanName.attr}" /> 


<p:commandButton id="someHtmlButtonId" 
        actionListener="#{beanName.doStuff}" 
        value="Button Label" 
        ajax="false" 
        immediate="true"/> 
  1. 入力名JSFは、いくつかの他の識別子を入れ、そして得られたパラメータ名は次のように見えるかもしれ前に名前フラグメントカウスでparametesを得る: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 ;) 
} 
関連する問題