3

<h:dataTable>チェックボックス、テキスト、およびテキストボックスを含むいくつかの行を表示するためにリストを反復しているJSFページがあります。

<h:dataTable>ユーザーがチェックボックスをオンにしたときに、テキストボックス内にテキストを入力する必要があるように、を検証する必要があります。

これは私の JSF ページです。

 <h:form prependId="false" id="form">
    <h:dataTable id="rm" width="100%" cellspacing="4"
    value="#{controller.alertTriggers}" var="alt"
        columnClasses="c1,c2,c3,c4">                    


            <h:column>
              <h:selectBooleanCheckbox value="#{alt.checkValue}" id="checkbox"/>
           </h:column>
            <h:column>
               <h:outputText value="#{alt.id}" />                                       
            </h:column>
            <h:column>
              <h:outputFormat value="#{alt.msg1}" />                              
            </h:column>
            <h:column>                                              
                 <h:message for="emailID" id="email" styleClass="validation-error"/>
                 <h:inputText value="#{alt.mailId}" id="emailID" style="width: 87%;" />

            </h:column>                                         

    </h:dataTable>                                          
</h:form>                                       

すべてのチェックボックスのcheckboxid を として、すべてのテキストボックスの id を として指定しましemailIDた。ページがレンダリングされると、ページのソースを確認すると、チェックボックスの ID が「rm:0:checkbox」、「rm:1:checkbox」... であり、テキストボックスの ID が「rm:0:」であることがわかりました。 emailID','rm:1:emailID'..

コントローラーでは、次のコードを使用してこれらの動的テキスト ボックスとチェック ボックスにアクセスしたいと考えています。

 FacesContext context = FacesContext. getCurrentInstance();


                  for (int i=0;i<9;i++){
                       UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":checkbox" );
                        if ((Boolean) u.getValue()){
                              UIInput ui=(UIInput) FacesContext.getCurrentInstance().getViewRoot().findComponent( "form:rm:" +i+":emailID" );

                               //code

                       }
                 }

しかし、これは java.lang.NullPointerException を与えています

コードを使用しても:

  UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
   findComponent( "form:rm:0:checkbox" ); gives the same exception.

しかし、私が使用する場合

     UIInput u=(UIInput) FacesContext.getCurrentInstance().getViewRoot().
       findComponent( "form:rm:checkbox" );

Null Pointer Exceptionは発生しませんが、どのチェックボックスの値が発生しているかはわかりません。

つまり、要約すると、

JSF は rm:1:checkbox、rm:2:checkbox などの ID を生成しますが、JSF ページでこの UI コンポーネントにアクセスしようとすると、アクセスできません。

何か不足していますか?

4

1 に答える 1

3

FacesContext#getViewRoot()、JSF コンポーネント ツリーを返します。これは、すべてのタグハンドラ(JSTL<ui:include>など)を考慮した後の XHTML ソース コードで表されるツリーとまったく同じです。そこには1つしかない ことを認識する必要が<h:selectBooleanCheckbox id="checkbox">あります。UIViewRoot#findComponent()正確にその IDで利用できます"form:rm:checkbox"

親の現在の反復ラウンドに応じて複数回再生成されるのは、HTML 表現だけ<h:dataTable>です。この生成された HTML 表現には、現在の行インデックスがインライン化されたクライアント ID があります。この HTML 表現は、明らかにコンポーネント ツリーでは利用できません。

コンポーネントの状態 (送信された値など) も、反復中にのみ使用でき<h:dataTable>、前後では使用できません。基本的に、コンポーネントが反復処理を行っていないときに、Bean のアクション メソッドでコンポーネントの値にアクセスしようとして<h:dataTable>いるため、値は常に を返しnullます。

プログラムで<h:dataTable>反復をシミュレートして目的の値を収集できるようにするには、<h:dataTable>byにアクセスして、実装UIComponent#visitTree()で関心のある情報を収集する必要があります。VisitCallback

UIData table = (UIData) viewRoot.findComponent("form:rm");
table.visitTree(VisitContext.createVisitContext(FacesContext.getCurrentInstance()), new VisitCallback() {
    @Override
    public VisitResult visit(VisitContext context, UIComponent target) {
        if (target instanceof HtmlSelectBooleanCheckbox) {
            HtmlSelectBooleanCheckbox checkbox = (HtmlSelectBooleanCheckbox) target;
            System.out.println("id: " + checkbox.getId());
            System.out.println("value: " + checkbox.getValue());
            // Collect them in an arraylist orso.
        }

        return VisitResult.ACCEPT;
    }
});

ただし、具体的な問題の解決に関しては、完全に間違った方向に進んでいます。アクションメソッドではなく、検証したい入力コンポーネントに関連付けられたバリデーターで検証を実行する必要があります。required同じ行のチェックボックスがオンになっている場合にのみ、入力フィールドを検証するという特定の具体的な機能要件を解決する方法は次のとおりです。

<h:column>
    <h:selectBooleanCheckbox binding="#{checkbox}" ... />
</h:column>
<h:column>                                              
    <h:inputText ... required="#{checkbox.value}" />
</h:column>

それで全部です。追加の利点は、バリデーターが反復に実行されるため、そのすべてのコードも<h:dataTable>必要ないことです。visitTree()

于 2013-09-02T12:51:31.497 に答える