我正在实现一个复合组件,我发现了一个我找不到解决方案的问题。
我指定了页面作者可以传递或不传递的属性,但我无法指定方法属性(Action的方法表达式),如果未传递,则复合组件不使用composite:implementation标签中的method属性。
这是我的代码:
<composite:interface>
<composite:attribute name="namePrompt" required="true"/>
<composite:attribute name="actionMethod" method-signature="java.lang.String action()" required="false"/>
<composite:attribute name="showComponent" default="false"/>
</composite:interface>
<composite:implementation>
<div>
<p:commandLink actionListener="#{cc.attrs.actionMethod}"
rendered="#{cc.attrs.showComponent}"
>
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
</div>
</composite:implementation>
使用它时,我没有指定“actionMethod”属性。像这样:
<util:foo namePrompt="SomeName" showComponent="true"/>
但我收到错误消息:
javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.actionMethod}'
有办法做到这一点吗?
答案 0 :(得分:10)
您必须创建两个p:commandLink
元素,并根据参数的定义有条件地渲染它们:
<p:commandLink actionListener="#{cc.attrs.actionMethod}" rendered="#{!empty cc.getValueExpression('actionMethod') and cc.attrs.showComponent}">
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
<p:commandLink rendered="#{empty cc.getValueExpression('actionMethod')}">
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
答案 1 :(得分:5)
将方法签名返回类型更改为java.lang.Object并添加&#34; null&#34;作为默认值。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Java</label>
<br />
<label>Python</label>
<br />
<label>Perl</label>
<br />
<script type="text/javascript">
var jq = jQuery.noConflict();
jq("label").after(" Programing");
</script>
没有方法:
<composite:interface>
<composite:attribute name="namePrompt" required="true"/>
<composite:attribute name="actionMethod" method-signature="java.lang.Object action()" required="false" default="null"/>
<composite:attribute name="showComponent" default="false"/>
</composite:interface>
<composite:implementation>
<div>
<p:commandLink actionListener="#{cc.attrs.actionMethod}"
rendered="#{cc.attrs.showComponent}"
>
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
</div>
</composite:implementation>
使用方法:
<util:foo namePrompt="SomeName" showComponent="true"/>
答案 2 :(得分:3)
另一种解决方案是使用操作方法创建自己的组件类型。例如:
<composite:interface componentType="myButton">
<composite:attribute name="namePrompt" required="true"/>
<composite:attribute name="actionMethod" method-signature="java.lang.String action()" required="false"/>
<composite:attribute name="showComponent" default="false"/>
</composite:interface>
<composite:implementation>
<div>
<p:commandLink actionListener="#{cc.action()}" rendered="#{cc.attrs.showComponent}">
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
</div>
</composite:implementation>
componentType必须如下所示:
@FacesComponent("myButton")
public class MyButton extends UINamingContainer {
public MyButton () {
}
public String action() {
MethodExpression me = (MethodExpression) this.getAttributes().get("actionMethod");
if (me != null) {
try {
Object result = me.invoke(FacesContext.getCurrentInstance().getELContext(), null);
if (result instanceof String) {
return (String) result;
}
} catch (ValidatorException ve) {
throw ve;
}
}
return null;
}
}
答案 3 :(得分:1)
有同样的确切错误,并且我的组件也需要一个可选的操作方法。
所以我尝试使用method-signature在composite属性上添加一个default参数,指向相应FacesComponent类上的一个方法,它运行得很好!
组件:
<composite:interface componentType="myButton">
<composite:attribute name="namePrompt" required="true"/>
<composite:attribute name="actionMethod" method-signature="java.lang.String action()" required="false" default="#{cc.dummyAction}"/>
<composite:attribute name="showComponent" default="false"/>
</composite:interface>
<composite:implementation>
<div>
<p:commandLink action="#{cc.attrs.actionMethod}"
rendered="#{cc.attrs.showComponent}"
>
<h:outputText value="#{cc.attrs.namePrompt}"/>
</p:commandLink>
</div>
</composite:implementation>
FacesComponent类:
@FacesComponent("myButton")
public class MyButton extends UINamingContainer {
public MyButton () {
}
public String dummyAction() {
return "";
}
}
答案 4 :(得分:0)
避免将方法放入复合材料中。如果您需要这样做,请将具有该方法的类放入Composite中,并像这样使用它:
<composite:interface>
<composite:attribute name="classWithMethod"
method-signature="java.lang.String"/>
</composite:interface>
执行:
<composite:implementation>
<div>
<p:commandLink
actionListener="#{cc.attrs.classWithMethod.actionMethod}">
</p:commandLink>
</div>
</composite:implementation>
为我工作! :D