JSF 2 — Composite component with optional listener attribute on f:ajax

前端 未结 3 1471
无人及你
无人及你 2020-12-15 01:45

I have a composite component that looks something like this:




        
相关标签:
3条回答
  • 2020-12-15 02:15

    You need to specify the method-signature attribute of the <cc:attribute> tag in order to treat the attribute value as a method expression. You can use the JSTL view build time tag <c:if> to conditionally add the <f:ajax> tag.

    <cc:interface>
        <cc:attribute name="listener" method-signature="void listener()" />
    </cc:interface>
    <cc:implementation>
        <h:someComponent>
            <c:if test="#{cc.getValueExpression('listener') != null}">
                <f:ajax listener="#{cc.attrs.listener}" />
            </c:if>
        </h:someComponent>
    </cc:implementation>
    

    (the #{not empty cc.attrs.listener} won't work as EL would implicitly evaluate the attribute as a value expression)

    Then you can use it as follows:

    <my:someComposite listener="#{bean.listener}" />
    

    Or when your environment doesn't support EL 2.2, then create a backing component:

    @FacesComponent("someComponent")
    public class SomeComponent extends UINamingContainer {
    
        public boolean isHasListener() {
            return getValueExpression("listener") != null;
        }
    
    }
    

    which is to be declared and used as

    <cc:interface type="someComponent">
        <cc:attribute name="listener" method-signature="void listener()" />
    </cc:interface>
    <cc:implementation>
        <h:someComponent>
            <c:if test="#{cc.hasListener}">
                <f:ajax listener="#{cc.attrs.listener}" />
            </c:if>
        </h:someComponent>
    </cc:implementation>
    
    0 讨论(0)
  • 2020-12-15 02:30

    I've the same problems too, and my solution was create default value for the action method. I have only to create a class: MyComponent.java that contains all default methods signature.

    <cc:interface>
        <cc:attribute name="listener" method-signature="void listener()"
                      default="#{myComponent.doNothing()}" />
    </cc:interface>
    <cc:implementation>
        <h:someComponent>
            <f:ajax listener="#{cc.attrs.listener}" />
        </h:someComponent>
    </cc:implementation>
    
    0 讨论(0)
  • 2020-12-15 02:41

    All of the above didn't work for me unfortunately, so I fiddled around and came up with the following solution.

    <cc:interface type="someComponent">
        <cc:attribute name="listener" method-signature="void listener()" />
    </cc:interface>
    <cc:implementation>
        <h:someComponent>
            <p:ajax listener="#{cc.attrs.listener}" onstart="#{cc.attrs.containsKey('listener') ? '' : 'return false'}" />
        </h:someComponent>
    </cc:implementation>
    

    This will always bind the ajax behavior, but only execute it if there actually is a listener.

    0 讨论(0)
提交回复
热议问题