2012-07-11 54 views
3

我有一些麻煩讓AJAX調用在Mojarra 2.0.3和PrimeFaces的嵌套複合組件中正確觸發。嵌套的JSF複合組件內的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組件外的頁面上。另外,如果我使用相同的容器結構,但不是實際的複合組件,則一切正常。

只要將子組件的子組件放置爲Container組件的子組件,這就是事物變得不可靠的地方。在子組件火災未正確Ajax調用(即保存commandLink)用Firebug幫助調試這一點,我已經能夠確定如下:

  • AJAX的POST請求似乎被髮送。 「開始」onevent正在發射,並且看着螢火蟲中的控制檯顯示正在向服務器發出的信息,併發送了正確的組件ID和值。
  • 支持bean中的操作未被調用。我有一個打印語句作爲第一行,它不是打印。
  • ajax請求似乎正在正確完成,一旦發生「成功」。
  • 頁面上沒有任何內容正在更新。表單不刷新,頁面頂部的p:messages對象也不刷新。

很顯然,我可以做到這一點,而該容器組件,但我寧願要能當然採取代碼重用的優點。我是否錯過了我需要做的一些事情來讓ajax正常工作?

回答

0

我相信你的問題是這樣的:

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

execute屬性可以參考特殊的關鍵字(如@this,@form,等等。),或根據文檔:

如果指定了文字,它必須是空格分隔的組件標識符和/或其中一個關鍵字。

當您將此組件作爲子組件插入父組件時,組件ID將通過動態確定並且無法完全引用。

+0

這似乎不是問題。如果我使用@form,結果是相同的,並且至少根據螢火蟲,正確的id將被髮送回服務器。 – moneyt 2012-07-12 12:52:55

+0

@moneyt它仍然是錯誤的,但老實說,如果正確的ID被髮送執行,我很難過。如果我是你,我會將JSF源文件附加到我的IDE庫並開始通過Mojarra。這可能會給你更多的線索。 – 2012-07-12 12:58:41

+1

你確定這是錯的嗎?在這種情況下,組件ID不是絕對的,而是相對的。我的理解是,如果沒有ID的前導「:」,它不是絕對的,JSF會搜索當前表單以獲得匹配的ID。我想如果它找不到ID,我會得到錯誤告訴我它無法解決它們。 – moneyt 2012-07-12 14:35:39

2

我與MyFaces 2.1.6有完全相同的問題。 我無法使用CC的接口中的ClientBehavior從嵌套的組合組件進行AJAX調用。

Like moneyT寫道服務器被通知ajax標記中指定的事件,但是當生命週期進入階段5 - 調用應用程序時,事件爲空,並且沒有偵聽器被調用。越來越多,它看起來像一個執行MyFaces的錯誤。

編輯:我發現了另一種解決方案,它比在複合組件中硬編碼ajax好得多。我已經將外部複合組件重構爲facelet。它失去了複合材料的一些怪癖,但它完成了工作。它也是可重用的。

(更一workaraund比溶液)唯一的解決辦法,我發現是硬編碼AJAX在複合組件,而不是使用ClientBehavior,像這樣:

<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> 

然而這種解決方法不是非常好,因爲複合組件背後的想法是你可以用很多不同的選項來重用它們。在其中硬編碼阿賈克斯限制了選項