JSF2.0 - Component component with optional method expression

I am implementing a composite component, and I found a problem that did not find a solution.

I specified my attributes, which may or may not be passed by the page author, but I cannot specify a method attribute (method expression for Action), which, if it was not passed, the composite component does not use the method attribute in the composite tag: tag.

Here is 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 this parameter, I did not specify the actionMethod attribute. Like this:

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

But I get an error message:

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

Is there any way to do this?

+6
source share
4 answers

You will need to create two p:commandLink elements p:commandLink and make them conditionally according to the 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> 
+10
source

Another solution is to create your own type of component using the 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 componentType should look like this:

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

Change the return method signature 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"/> 

Using the method:

 <util:foo actionMethod="#{someBean.someMethod()}" namePrompt="SomeName" showComponent="true"/> 
+3
source

Had the exact same error and should have had an optional action method for my component.

So, I tried to add the default parameter to the composite attribute using the signature method, pointing to the method of the corresponding FacesComponent class, and it works great!

component:

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

 @FacesComponent("myButton") public class MyButton extends UINamingContainer { public MyButton () { } public String dummyAction() { return ""; } } 
+1
source

All Articles