我正在尝试为按钮创建一个JSF 2.1复合组件:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jstl/core">
<composite:interface>
<composite:attribute name="id" required="true" type="java.lang.String" />
<composite:attribute name="label" required="true" type="java.lang.String" />
<composite:attribute name="action" method-signature="java.lang.String action()" targets="#{cc.attrs.id}" />
</composite:interface>
<composite:implementation>
<a4j:commandLink id="#{cc.attrs.id}">
<span style="linkButton"><h:outputText value="#{cc.attrs.label}" /></span>
</a4j:commandLink>
</composite:implementation>
</html>
我对此代码的问题是,在呈现页面时它会出现以下异常:
java.lang.ClassCastException: javax.faces.component.UINamingContainer cannot be cast to javax.faces.component.ActionSource2
at com.sun.faces.application.view.FaceletViewHandlingStrategy$MethodRetargetHandlerManager$ActionRegargetHandler.retarget(FaceletViewHandlingStrategy.java:1536)
at com.sun.faces.application.view.FaceletViewHandlingStrategy.retargetMethodExpressions(FaceletViewHandlingStrategy.java:689)
at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.applyNextHandler(CompositeComponentTagHandler.java:201)
at org.richfaces.view.facelets.html.BehaviorsAddingComponentHandlerWrapper.applyNextHandler(BehaviorsAddingComponentHandlerWrapper.java:53)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:196)
...
当我使用#{cc.attrs.id}
之类的定义字符串替换id
和targets
属性中的myId
时,该组件按预期工作但这使得它不能在同一个字段中重复使用页面,因此首先消除了创建复合组件的感觉。
我在这里错过了什么吗?
答案 0 :(得分:11)
在JSF组件树中,#{cc.attrs.id}
已经使用<cc:implementation>
。您不应该在另一个组件上重用任何使用过的组件ID。您的具体功能要求不清楚,投诉“不能在同一页面重复使用”真的没有意义,因为它完全正常(你实际上尝试过它并调查生成的HTML输出?),所以它是很难理解你所面临的问题。也许您完全忽略了复合组件隐式继承自NamingContainer
并且已经将自己的id添加到子项的ID中,如<h:form>
,<h:dataTable>
等也可以吗?
如果您的唯一要求是能够像<f:ajax render="compositeId" />
那样通过ajax从外部引用复合组件,那么您需要将<cc:implementation>
的正文包裹在普通的HTML <span>
中或<div>
如下#{cc.clientId}
代替:
<div id="#{cc.clientId}">