3

Mojarra2.0.3とPrimeFacesを使用してネストされた複合コンポーネントでAJAX呼び出しを適切に起動するのに少し問題があります。

子複合コンポーネントは次のようになります。

<cc:interface componentType="therapy">
    <cc:attribute name="therapyType" type="java.lang.String" required="true"/>
    <cc:attribute name="patientId" type="java.lang.String" required="true"/>
    <cc:attribute name="showHistory" type="java.lang.Boolean" required="false" default="true"/>
    <cc:attribute name="width" type="java.lang.String" required="false" default="350px"/>
    <cc:attribute name="maxHistory" type="java.lang.String" required="false" default="3"/>
    <cc:attribute name="collectDoctor" type="java.lang.Boolean" required="false" default="false"/>
    <cc:attribute name="collectCareDate" type="java.lang.Boolean" required="false" default="false"/>
    <cc:attribute name="important" type="java.lang.Boolean" requred="false" default="false"/>
</cc:interface>

<cc:implementation>

    <script>
        function #{cc.clientId}Toggle(){
            $("##{cc.clientId}_newbutton").toggle();
            $("##{cc.clientId}_savebuttons").toggle();

            if(#{cc.attrs.collectDoctor}){
                $("##{cc.clientId}_doctor").toggle();
            }

            if(#{cc.attrs.collectCareDate}){
                $("##{cc.clientId}_care").toggle();
            }

            $("##{cc.clientId}_newTherapy").toggle(50);
        }

        function #{cc.clientId}rowHighlight(event){
            if(event.status == 'begin'){
                $("##{cc.clientId}_loader").toggle();
            }
            if(event.status == 'success'){
                $("##{cc.clientId}\\:histTable tr:eq(1)").effect("highlight", {color:"#FED17A", easing:"easeInCubic"}, 2000);
            }
        }

        $(function(){
            if(#{cc.attrs.important}){
                $("div[class~='ui-panel-titlebar'][id^='#{cc.clientId}']").css("background", "#FED17A");
            }
        });
    </script>

    <h:form prependId="false">
        <p:panel styleClass="mcoPanel" style="width:#{cc.attrs.width};">
                <f:facet name="header">
                    <h:panelGroup>
                        <span id="#{cc.clientId}_title">#{cc.myType.word}</span>
                        <span id="#{cc.clientId}_newbutton" class="mcoPanel-controls">
                            <span onclick="#{cc.clientId}Toggle();">
                                <h:graphicImage name="page_new.gif" library="images"/>
                            </span>
                        </span>
                        <span id="#{cc.clientId}_savebuttons" class="mcoPanel-controls" style="display:none;">
                            <span id="#{cc.clientId}_loader" style="display:none;">
                                <h:graphicImage name="ajax-loader.gif" library="images" height="16" width="16"/>
                            </span>
                            <h:commandLink action="#{cc.saveNewTherapy}">
                                <f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" render="@form" onevent="#{cc.clientId}rowHighlight"/>
                                <h:graphicImage name="action_save.gif" library="images"/>
                            </h:commandLink>
                            <span onclick="#{cc.clientId}Toggle();">
                                <h:graphicImage name="page_cross.gif" library="images"/>
                            </span>
                        </span>
                    </h:panelGroup>
            </f:facet>
            <div id="#{cc.clientId}_newTherapy" class="mcoPanel-new" style="display:none;">
                <h:outputLabel for="newOnTherapy" value="Satisfied:" style="position:relative; top: -10px;"/>
                <p:selectOneMenu id="newOnTherapy" label="Satisfied" value="#{cc.newOnTherapyValue}" style="width: 60px;">
                    <f:selectItem itemLabel=""/>
                    <f:selectItems value="#{cc.yesNoList}"/>
                </p:selectOneMenu>
                <br/>
                <h:outputLabel for="newExemption" value="Exemption:" style="position:relative; top: -10px;"/>
                <p:selectOneMenu id="newExemption" value="#{cc.newExemption}" style="width: 150px;">
                    <f:selectItems value="#{cc.exemptions}"/>
                </p:selectOneMenu>
                <span id="#{cc.clientId}_doctor" style="display:none">
                    <br/>
                    <h:outputLabel for="newDoctor" value="Doctor:"/>
                    <p:inputText id="newDoctor" value="#{cc.newDoctor}"/>
                </span>
                <span id="#{cc.clientId}_care" style="display:none">
                    <br/>
                    <h:outputLabel for="newCareDate" value="Care Date:"/>
                    <p:calendar id="newCareDate" label="Care Date" value="#{cc.newCareDate}" showButtonPanel="true">
                        <f:converter converterId="dateOfBirthConverter"/>
                    </p:calendar>
                </span>
            </div>
            <h:messages id="#{cc.clientId}_messages" errorClass="errorMessage"/>
            <p:dataTable id="histTable" value="#{cc.history}" var="item" rendered="#{cc.attrs.showHistory}">
                <!-- Table Output -->
            </p:dataTable>
        </p:panel>
    </h:form>

そして、親の複合コンポーネントは次のようになります。

<cc:interface>
    <cc:attribute name="title" type="java.lang.String" required="true"/>
</cc:interface>

<cc:implementation>

    <h:outputScript name="containerpanel.js" library="js/components" target="head"/>

    <p:panel toggleable="true" styleClass="contentPanel" toggleSpeed="500" style="width:1100px;">
        <f:facet name="header">
            #{cc.attrs.title}
            <div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentSaveAll">
                Save All
            </div>
            <div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentExpandAll">
                ++
            </div>
            <div class="ui-panel-titlebar-icon ui-corner-all ui-state-default contentCollapseAll">
                - -
            </div>
        </f:facet>

        <cc:insertChildren>
                     <!-- Child components go here -->
        </cc:insertChildren>

    </p:panel>

</cc:implementation>

実装では、コンテナコンポーネント内に任意の数の子コンポーネントを許可することになっています。

子コンポーネントは、コンテナコンポーネントの外部のページに配置されている場合、ajaxリクエストを送信し、内部コンポーネントを完全に更新します。さらに、コンテナの同じ構造を使用しているが、実際の複合コンポーネントを使用していない場合は、すべてが正常に機能します。

子コンポーネントをContainerコンポーネントの子として配置するとすぐに、問題が発生します。子コンポーネントでのajax呼び出しが正しく起動しません(つまり、save commandLink)これをデバッグするためにfirebugを使用して、次のことを確認できました。

  • ajaxpostリクエストが送信されているようです。「begin」oneventが発生し、firebugでコンソールを見ると、サーバーに投稿が行われ、適切なコンポーネントIDと値が返送されていることがわかります。
  • バッキングBeanのアクションは呼び出されていません。最初の行にprintステートメントがありますが、印刷されていません。
  • ajaxリクエストは正しく完了しているようで、イベントの「成功」が発生しています。
  • このページでは何も更新されていません。フォームは更新されず、ページ上部のp:messagesオブジェクトも更新されません。

明らかに、Containerコンポーネントなしでこれを行うことができますが、もちろんコードの再利用を利用できるようにしたいと思います。ajaxを正しく機能させるために必要な、明らかな何かがここにありませんか?

4

2 に答える 2

2

MyFaces 2.1.6 でもまったく同じ問題が発生しています。CC のインターフェイスで ClientBehavior を使用して、ネストされた複合コンポーネントから AJAX 呼び出しを行うことができません。

moneyT が書いたように、ajax タグで指定されたイベントがサーバーに通知されますが、ライフサイクルがフェーズ 5 - Invoke Application に移行したとき、イベントは null で、リスナーは呼び出されませんでした。MyFaces の実装におけるバグのように見えることがますます多くなっています。

編集:複合コンポーネントでajaxをハードコーディングするよりもはるかに優れた別のソリューションを見つけました。外側の複合コンポーネントを facelet にリファクタリングしました。コンポジットの癖のいくつかを失いますが、仕事は完了します. また、再利用可能です。

私が見つけた唯一の解決策 (解決策というよりも回避策) は、次のように、ClientBehavior を使用するのではなく、複合コンポーネントで ajax をハードコーディングすることです。

   <composite:implementation>            
       <h:panelGroup layout="block" id="listBox" class="list-box-scroll-pane" style="height:#{cc.attrs.visibleLines*27 + 5}px; width:#{cc.attrs.width}px">
        <h:inputText id="submit-value" style="visibility: hidden; width:0px; height: 0px;" value="#{cc.attrs.property}">
                 <f:ajax event="change"
                  render="carModel"
                  listener="#{carDetailsMediator.changeCarMake}" 
                  onevent="initComboboxes"/>
        </h:inputText>
        <ui:repeat value="#{cc.attrs.items}" var="element" varStatus="loop">
            <input id="input-#{cc.attrs.customId}-#{loop.index}" type="hidden" 
                            value="#{element.value}" />
            <div id="div-#{cc.attrs.customId}-#{loop.index}" class="list-box-row">#{element.label}</div>
        </ui:repeat>    

        </h:panelGroup>
    </composite:implementation>

ただし、この回避策はあまり良くありません。複合コンポーネントの背後にある考え方は、それらをさまざまなオプションで再利用できるということだからです。その中でajaxをハードコーディングすると、オプションが制限されます

于 2012-07-16T10:05:53.537 に答える
0

あなたの問題はこれだと思います:

<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" ...

execute属性は、特別なキーワード (例: @this、@form など) またはドキュメントに従って参照できます。

リテラルが指定されている場合は、スペースで区切られたコンポーネント識別子の文字列および/またはキーワードの 1 つでなければなりません。

このコンポーネントを子として親コンポーネントに挿入する場合、コンポーネント ID は動的に決定され、絶対に参照することはできません。

于 2012-07-12T12:12:06.710 に答える