我在使用Mojarra 2.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组件外部的页面上)。另外,如果我使用相同的容器结构,而不是实际的复合组件,一切都可以正常工作。
只要将子组件放置为Container组件的子组件,就会出现问题。没有ajax调用子组件正常激活(即save commandLink)使用firebug来帮助调试它,我已经能够确定以下内容:
显然我可以在没有Container组件的情况下做到这一点,但我宁愿能够利用代码重用。我是否遗漏了一些明显的东西,我需要做的是让ajax正常工作?
答案 0 :(得分:2)
我遇到与MyFaces 2.1.6完全相同的问题。 我无法在CC的界面中使用ClientBehavior从嵌套的Composite Components进行AJAX调用。
与moneyT写道,服务器正在收到ajax标记中指定的事件的通知,但是当生命周期进入第5阶段 - 调用应用程序时,事件为空且未调用任何侦听器。它越来越像是MyFaces实现中的一个错误。
编辑:我找到了另一种解决方案,它比复合组件中的ajax硬编码要好得多。我已经将外部复合组件重构为facelet。它失去了复合材料的一些怪癖,但它完成了工作。它也是可以重复使用的。
我找到的唯一解决方案(更多的是工作游戏而非解决方案)是在复合组件中硬编码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>
但是这种解决方法并不是很好,因为复合组件背后的想法是你可以使用许多不同的选项重用它们。在其中硬编码ajax限制了选项。
答案 1 :(得分:0)
我相信你的问题是:
<f:ajax execute="newOnTherapy newExemption newDoctor newCareDate" ...
execute
属性可以引用特殊关键字(例如@this,@ form等)或根据文档:
如果指定了文字,则它必须是以空格分隔的组件标识符字符串和/或其中一个关键字。
当您将此组件作为子组件插入父组件时,组件ID将通过动态确定并且无法绝对引用。