JSF2.0 - Composite component with optional method expression

前端 未结 5 1878
没有蜡笔的小新
没有蜡笔的小新 2021-01-02 16:12

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,

相关标签:
5条回答
  • 2021-01-02 16:48

    Had the same exact error and needed to have an optional action method on my component too.

    So I have tried adding a default parameter on the composite attribute with the method-signature, pointing to a method on 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 "";
        }
    
    }
    
    0 讨论(0)
  • 2021-01-02 16:50

    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;
        }
    }
    
    0 讨论(0)
  • 2021-01-02 16:53

    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>
    
    0 讨论(0)
  • 2021-01-02 17:01

    Avoid puting methods inside composite. If tou need to do that, put the class that have the method inside composite, and use it like this:

    <composite:interface>
       <composite:attribute name="classWithMethod" 
                            method-signature="java.lang.String"/>
    </composite:interface>
    

    And the implementation:

    <composite:implementation>
       <div>
          <p:commandLink 
             actionListener="#{cc.attrs.classWithMethod.actionMethod}">    
          </p:commandLink>
       </div>
    </composite:implementation>
    

    Worked for me! :D

    0 讨论(0)
  • 2021-01-02 17:05

    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"/>
    
    0 讨论(0)
提交回复
热议问题