8

我正在实现一个复合组件,但我发现了一个我没有找到解决方案的问题。

我指定了页面作者可以或不可以传递的属性,但我无法指定方法属性(Action 的方法表达式),如果未传递,则复合组件不使用方法属性在复合:实现标签中。

这是我的代码:

<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}'

有没有办法做到这一点?

4

5 回答 5

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>
于 2013-03-15T19:42:00.307 回答
7

将方法签名返回类型更改为 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"/>
于 2016-08-09T08:56:18.207 回答
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;
    }
}
于 2014-01-22T13:56:16.240 回答
1

有同样的错误,也需要在我的组件上有一个可选的操作方法。

因此,我尝试使用方法签名在复合属性上添加默认参数,指向相应 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 "";
    }

}
于 2015-06-30T10:59:43.350 回答
0

避免将方法放在复合材料中。如果您需要这样做,请将具有该方法的类放在组合内,并像这样使用它:

<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

于 2018-07-24T16:31:55.490 回答