PrimeFaces复合组件中动态设置的dataTable id如何被dataExporter正确引用
问题原因
你传入的id属性本质是赋值给复合组件本身(JSF中复合组件默认是UINamingContainer命名容器实例),你再把这个id值同步给内部p:dataTable时,组件树的结构为:复合组件(id=你传入的参数值) 下嵌套 p:dataTable(id=你传入的参数值)。p:dataExporter查找目标组件时,会优先命中上层的复合组件本身,命中的组件类型是UINamingContainer而非DataTable,因此触发类型不匹配报错。
最优解决方案
复合组件内部的组件id天然受命名容器隔离,同一页面复用组件时,内部id会自动带上当前复合组件的客户端id作为前缀,完全不会出现id冲突,你不需要动态传入内部p:dataTable的id,直接使用固定id即可:
<composite:implementation> <p:outputPanel> <p:fieldset> <!-- 内部用固定id,命名容器自动隔离不会冲突 --> <p:dataTable id="internalTable" emptyMessage="#{msgs.dataTable_emptyMessage}" var="myVar" value="#{cc.attrs.data}" lazy="true" rows="20" paginator="true" currentPageReportTemplate="({startRecord} - {endRecord} von {totalRecords})" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}" widgetVar="#{cc.attrs.widgetVarName}"> ... 表格结构定义 ... </p:dataTable> <div class="footer"> <div style="float: right;"> <p:commandButton value="Excel-Export" ajax="false" icon="fa fa-file-excel-o" title="someTitle" > <!-- 直接引用内部固定id即可 --> <p:dataExporter target="internalTable" type="xls" postProcessor="#{documentService.postProcessXLS}" encoding="UTF-8" fileName="fn"></p:dataExporter> </p:commandButton> </div> </div> </p:fieldset> </p:outputPanel> </composite:implementation>
备选方案(特殊场景需要动态设置内部table id时使用)
如果你确实需要动态指定内部p:dataTable的id,可以在target属性中明确标注查找的根节点为当前复合组件:
<p:dataExporter target=":#{cc.clientId}:#{cc.attrs.id}" type="xls" postProcessor="#{documentService.postProcessXLS}" encoding="UTF-8" fileName="fn"></p:dataExporter>
说明:
widgetVar是全局JS变量名,不存在命名容器隔离,因此你动态传值避免冲突的逻辑是正确的,不需要调整。
内容的提问来源于stack exchange,提问作者Christian O.
相关产品推荐
相关产品推荐

