web-dev-qa-db-ja.com

JSFはフィールド間検証をサポートしていません。回避策はありますか?

JSF 2.0では、特定の長さであるかどうかを確認するチェックのように、1つのフィールドの入力のみを検証できます。 「都市と州を入力するか、郵便番号のみを入力する」というフォームは使用できません。

これをどのように回避しましたか?私は、JSFの検証フェーズに関連する回答にのみ興味があります。マネージドBeanに検証ロジックを配置することに興味はありません。

35

これまで見てきた最も簡単なカスタムアプローチは、<h:inputHidden>を使用して<f:validator>フィールドを作成し、関連するすべてのコンポーネントを<f:attribute>として参照することです。検証するコンポーネントbeforeを宣言すると、 UIInput#getSubmittedValue()によって、バリデーター内で送信された値を取得できます

例えば。

<h:form>
    <h:inputHidden id="foo" value="true">
        <f:validator validatorId="fooValidator" />
        <f:attribute name="input1" value="#{input1}" />
        <f:attribute name="input2" value="#{input2}" />
        <f:attribute name="input3" value="#{input3}" />
    </h:inputHidden>
    <h:inputText binding="#{input1}" value="#{bean.input1}" />
    <h:inputText binding="#{input2}" value="#{bean.input2}" />
    <h:inputText binding="#{input3}" value="#{bean.input3}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:message for="foo" />
</h:form>

(非表示の入力のvalue="true"に注意してください。実際の値は実際には問題ではありませんが、nullまたは空の場合、バリデーターが必ずしも実行されるとは限らないことに注意してください、JSFのバージョンと構成に応じて)

@FacesValidator(value="fooValidator")
public class FooValidator implements Validator {

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        UIInput input1 = (UIInput) component.getAttributes().get("input1");
        UIInput input2 = (UIInput) component.getAttributes().get("input2");
        UIInput input3 = (UIInput) component.getAttributes().get("input3");
        // ...

        Object value1 = input1.getSubmittedValue();
        Object value2 = input2.getSubmittedValue();
        Object value3 = input3.getSubmittedValue();
        // ...
    }

}

検証するコンポーネントの<h:inputHidden>afterを宣言した場合、関連するコンポーネントの値は既に変換および検証されており、 UIInput#getValue() または多分 UIInput#getLocalValue()UIInputがない場合 isValid() )代わりに。

以下も参照してください。


または、そのためにサードパーティのタグ/コンポーネントを使用できます。 RichFaces には、たとえば <rich:graphValidator> タグがあり、 Seam3 には <s:validateForm> があり、 OmniFaces にはいくつかの標準 <o:validateXxx> このコンポーネントはすべて こちらに表示されます 。 OmniFacesは、コンポーネントベースのアプローチを使用して、ジョブを UIComponent#processValidators() で実行します。また、 カスタマイズ できるので、上記を以下のように実現できます。

<h:form>
    <o:validateMultiple id="foo" components="input1 input2 input3" validator="#{fooValidator}" />
    <h:inputText id="input1" value="#{bean.input1}" />
    <h:inputText id="input2" value="#{bean.input2}" />
    <h:inputText id="input3" value="#{bean.input3}" />
    <h:commandButton value="submit" action="#{bean.submit}" />
    <h:message for="foo" />
</h:form>

@ManagedBean
@RequestScoped
public class FooValidator implements MultiFieldValidator {

    @Override
    public boolean validateValues(FacesContext context, List<UIInput> components, List<Object> values) {
        // ...
    }
}

唯一の違いは、booleanを返すことと、メッセージを<o:validateMultiple>message属性として指定する必要があることです。

57
BalusC

Apache ExtVal はここでは言及されていません。

その中にいくつかの相互検証があります(他の有効な検証の中でも特に):

https://cwiki.Apache.org/confluence/display/EXTVAL/Property+Validation+Usage#PropertyValidationUsage-CrossValidation

1
Jens