2012-07-11 25 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> 

然而这种解决方法不是非常好,因为复合组件背后的想法是你可以用很多不同的选项来重用它们。在其中硬编码阿贾克斯限制了选项