Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF2.0 - Composite component with optional method expression

I'm implementing a composite component and I found a issue which I didn't find a solution.

I specified its attributes that can or not be passed by the page author, but I couldn't specify a method attribute (a method expression to Action) that, if it wasn't passed, the composite component doesn't use the method attribute in the composite:implementation tag.

Here my code:

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

When using it, I didn't specify the "actionMethod" attribute. Like this:

<util:foo namePrompt="SomeName" showComponent="true"/>

But I get the error message:

javax.faces.FacesException: Unable to resolve composite component from using page using EL expression '#{cc.attrs.actionMethod}'

Is there a way to do this?

like image 540
Erick Alves Avatar asked Mar 14 '13 21:03

Erick Alves


3 Answers

You will have to create two p:commandLink elements and render them conditionally according to definition of your parameter:

<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>
like image 81
partlov Avatar answered Mar 06 '23 07:03

partlov


Change the method signature return type to java.lang.Object and add "null" as the default value.

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

Without method:

<util:foo namePrompt="SomeName" showComponent="true"/>

With method:

<util:foo actionMethod="#{someBean.someMethod()}" namePrompt="SomeName" showComponent="true"/>
like image 31
Thogor Avatar answered Mar 06 '23 07:03

Thogor


An other solution is to create an own component type, with a action method. Example:

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

And the componentType has to look like:

@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;
    }
}
like image 22
h2mch Avatar answered Mar 06 '23 05:03

h2mch