1

コンポーネント フレームワークとして Prime Faces 3.4.1 を使用し、サーバー側フレームワークとして JSF 2.0 を使用しています。

以下は私の要件です

1)「会議が必要」というラベルの付いたフィールドがあります。次に、SelectOneRadio に「いいえ」と「はい」の 2 つのオプションを指定し、デフォルト値を「いいえ」に設定します。JSF/HTML コンポーネント h:SelectOneRadio を使用しています。

2) カレンダー コンポーネントである別のフィールドがあり、これはプライムフェイス カレンダー コンポーネントです。ユーザーが「会議が必要」であることを示す「はい」を選択した場合、ユーザーはカレンダー コントロールから日付を選択する必要があります。

3) ユーザーが「はい」を選択して日付を選択しない場合、日付を選択する必要があることを示す検証メッセージが表示されます。

Custom Validation コンポーネントを作成して SelectOneRadio にアタッチすると、カスタム バリデーターで選択した値を確認できます。ここで、UIComponent.getParent().findCompoent("rvmDate") を使用して、Calendar コンポーネントから値を取得して値が空かどうかを確認しようとしましたが、コンポーネントを取得しましたが、日付コンポーネントかどうかを確認する方法がわかりません。空であるか、任意の値が含まれています。

ユーザーが選択した日付の値を取得するのを手伝ってください。

問題を解決するために私を助けてください。それとも他に方法はありますか?ソースコードを見つけてください。

XHTML ページ

<h:selectOneRadio id="rvmMeetingOption"
    readonly="#{wipMB.rvmMeetingOptionReadOnly}"
    value="#{wipMB.requirementsMeeting}" 
    disabled="#{wipMB.rvmMeetingOptionDisabled}"
    validator="#{wipMB.validateRVMDate}"
    validatorMessage="Please enter RVM Date>

     <f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
     <f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
     <f:attribute value="#{rvmDateComp}" name="rvmDateComp"></f:attribute>
</h:selectOneRadio>

<p:calendar id="rvmDate" 
        readonly="#{wipMB.rvmMeetingDateReadOnly}"
        disabled="#{wipMB.rvmMeetingDateDisabled}"
        readonlyInput="true"
        navigator="true" mode="popup" 
        pattern="dd/MM/yyyy" 
        value="#{wipMB.rvmDate}" 
        effect="explode" 
        yearRange="1900:2500" 
        style="margin-left:5px"
        binding="#{rvmDateComp}"
</p:calendar>
<p:message id="rvmDateMsg" for="rvmDate" display="both" ></p:message>

カスタムバリデーター

public void validateRVMDate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException
{
    String invalidDate;
    String rvmOption;
    Date rvmDate;
    String rvmDt = "";

    try
    {

        FacesContext fc = FacesContext.getCurrentInstance();

        rvmOption = value.toString();
        DateFormat formatter = new SimpleDateFormat("E MMM dd HH:mm:ss Z yyyy");


        UIInput rvmCompDt = (UIInput)component.getAttributes().get("rvmDateComp");

        rvmDateId = rvmCompDt.getId();
        rvmDt = rvmCompDt.getSubmittedValue() == null ? "" : rvmCompDt.getSubmittedValue().toString();


        if (rvmOption.equals("1") && rvmDt.isEmpty())
        {

            FacesMessage msg = new FacesMessage("RVM date is required");
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            fc.addMessage("rvmDateMsg", msg);
            throw new ValidatorException(msg);

        }
    }

    catch (Exception ex)
    {
        String msg = ex.getMessage();
    }
}
4

3 に答える 3

3

JSF では、各コンポーネントは独自の小さな MVC スタックです。モデル (値として格納)、コントローラー (コンポーネント オブジェクト)、およびビュー (レンダラー) があります。バリデーターとコントローラーはアーキテクチャーの一部であり、モデルとビューの間で値を移動するために必要です。

JSF バリデーターは重要な役割を果たしますが、重要なのはこの小さな MVC スタックの内部だけです。それらは「フォームを検証する」ように設計されたのではなく、厳密に「コンポーネントの値を検証する」ように作られています。残念なことに、「バリデーター」という名前は、JSF に来るすべての人に、検証を行う必要があるたびにバリデーターが解決策であると考えさせます。奇妙なことに、コンバーターはそれほど乱用されていません。

あなたの場合、カスタムバリデーターを構築すると、次のような奇妙な状況が発生しました。

  • バリデーターとビューは互いに循環依存関係にあり、
  • ハック (「即時」など) と低レベル API を使用する必要がある。
  • ありそうもない場所でのビュー ロジックのハードコーディング、
  • より多くの知識を必要とし、不安定です。たとえば、ラジオボタンがドキュメント順でカレンダーの前か後かによって、カレンダーから値を取得するロジックが異なる場合があります。

上記の問題は解決できる可能性がありますが、すべて JSF アーキテクチャの悪用に起因するものであるため、問題を再考した方がよいと思います。検証はアプリケーションのフローに関係するため、すべての複雑さが条件付きの「addMessage」を持つ単一の単純な「if」ステートメントに分解されるアクション メソッドに最適です。

于 2013-02-08T10:16:12.403 に答える
3

immediate="true"最初にから削除する必要があります<p:calendar>。そうしないと、ラジオ ボタンが処理されるときにまったく処理されません。

次に、文字列がnullまたは空かどうかを確認するには、次のようにします

String dt = (String) uiCalendar.getSubmittedValue();

if (dt == null || dt.isEmpty()) {
    // dt is null or empty. Throw validator exception depending on the 
    // current radio button value. Note: you should not catch it yourself!
}

これは JSF とは何の関係もないことに注意してください。それは単なる基本的なJavaです。あなたの最初の試みif (dt == "")は実際には完全に無効です。はStringオブジェクトであり、プリミティブではありません。は==、内部値ではなく、参照によってオブジェクトを比較します。if (dt.equals(""))技術的には、代わりに使用する必要がありましたが、 のisEmpty()方が優れています。


具体required的な問題とは関係ありませんが、はるかに簡単な方法は、カレンダー コンポーネントの属性でラジオ ボタンの値を確認することです。binding最初にラジオ ボタン コンポーネントをビューの変数にバインドし、次に属性でそのUIInput#getValue()メソッドを参照しrequiredます。

<h:selectOneRadio id="rvmMeetingOption" binding="#{rvmMeetingOption}"
        readonly="#{wipMB.rvmMeetingOptionReadOnly}"
        value="#{wipMB.requirementsMeeting}" 
        disabled="#{wipMB.rvmMeetingOptionDisabled}">
    <f:selectItem itemLabel="No" itemValue="0"></f:selectItem>
    <f:selectItem itemLabel="Yes" itemValue="1" ></f:selectItem>
</h:selectOneRadio>

<p:calendar id="rvmDate" 
        readonly="#{wipMB.rvmMeetingDateReadOnly}"
        disabled="#{wipMB.rvmMeetingDateDisabled}"
        readonlyInput="true"
        navigator="true" mode="popup" 
        pattern="dd/MM/yyyy" 
        value="#{wipMB.rvmDate}" 
        effect="explode" 
        yearRange="1900:2500" 
        style="margin-left:5px"
        required="#{rvmMeetingOption.value == 1}">
</p:calendar>
于 2013-02-08T11:35:05.197 に答える
0

使用する

UIInput uiCalendar = (UIInput) component.getParent().findComponent("rvmDate");
Date test = uiCalendar.getValue();
if(test==null){
throw ValidatorException
}

テストでは、日付が入力されるか、日付フィールドで何も選択されていない場合は null になります

于 2013-02-08T08:43:03.557 に答える