JSF2.0 - 具有可选方法表达式的复合组件
Posted
技术标签:
【中文标题】JSF2.0 - 具有可选方法表达式的复合组件【英文标题】:JSF2.0 - Composite component with optional method expression 【发布时间】:2013-03-03 10:33:41 【问题描述】:我正在实现一个复合组件,但我发现了一个我没有找到解决方案的问题。
我指定了页面作者可以或不可以传递的属性,但是我无法指定方法属性(Action 的方法表达式),如果未传递,则复合组件不会使用Composite:implementation 标签中的方法属性。
这是我的代码:
<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'
有没有办法做到这一点?
【问题讨论】:
您可以将可选属性传递给actionListener
。你是什么用例,当actionListener
没有被解析并且commandLink
被渲染时,你认为应该发生什么?
是的,链接组件已呈现,但是当链接组件中发生单击操作时,它抱怨我没有为属性 actionMethod 定义方法。但这是我的意图,有时我不想为 actionMethod 属性定义一个动作方法。这可能吗?我认为把'required = false'解决问题。
【参考方案1】:
您必须创建两个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>
【讨论】:
【参考方案2】:将方法签名返回类型更改为java.lang.Object,并添加“null”作为默认值。
<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"/>
使用方法:
<util:foo actionMethod="#someBean.someMethod()" namePrompt="SomeName" showComponent="true"/>
【讨论】:
【参考方案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>
并且组件类型必须看起来像:
@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;
【讨论】:
【参考方案4】:有同样的错误,我的组件也需要一个可选的操作方法。
所以我尝试使用方法签名在复合属性上添加一个默认参数,指向相应 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 "";
【讨论】:
【参考方案5】:避免将方法放在复合材料中。如果您需要这样做,请将具有该方法的类放在组合中,并像这样使用它:
<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
【讨论】:
以上是关于JSF2.0 - 具有可选方法表达式的复合组件的主要内容,如果未能解决你的问题,请参考以下文章
JSF 复合组件支持 bean EL 表达式作为必需属性的默认值失败,方法未知
JSF 2——在 f:ajax 上具有可选监听器属性的复合组件
JSF 2.0 复合组件 - ajax 渲染参数 OUTSIDE 组件定义