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 に追加すると、検証エラーがあってもメソッドを実行できます。ただし、検証エラーは引き続き発生し、ここに表示されます。

2 つのオプションが表示されます。

1) immediate="true" を使用し、検証エラーを表示しない

検証しないボタンの場合、immediate="true" を設定し、h:messages の場合は次のようにします。

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

次に、そのパラメーターを送信するように Save-button (実際にフォームを保存しようとする必要があります) を設定します。

<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 Validation を単純に使用して、宣言時にスキップするにはどうすればよいですか?

4

4 に答える 4

9

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

更新

サンプルフォームの変更:

<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();
}
...
于 2011-01-31T15:30:08.323 に答える
8

属性disabledを持つタグf:validateBeanを使用して、Bean 検証を無効にすることができます。

例:

<h:inputText value="#{bean.name}">
   <f:validateBean disabled="#{anotherBean.flag}"/>
</h:inputText>
于 2011-02-09T02:22:47.163 に答える
2

この問題の解決策を公開しました。詳細はこちら: http ://www.springfuse.com/2011/12/15/skip-jsf-validation-depending-on-action.html

つまり、validateBeanタグのバインディング属性を利用します。そうすることで、validateメソッドをインターセプトし、クリックされたボタンに基づいて、それを通過させるかどうかを決定できます。

于 2011-12-16T14:56:17.173 に答える
-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. BeandoStuffメソッドでは、入力名 JSF が他の識別子を配置する前に、フラグメント名によってパラメーターを取得し、結果のパラメーター名は次のようになります。
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 ;)
}
于 2012-04-03T10:01:47.257 に答える