JSF2 composite components: are #{cc.childCount} and mutually exclusive?

后端 未结 3 2013
日久生厌
日久生厌 2021-01-18 02:44

I just dont get it: If I want my composite component to insert children, I use but #{cc.childCount}

相关标签:
3条回答
  • 2021-01-18 03:19

    From the cc:insertChildren documentation:

    Any child components or template text within the composite component tag in the using page will be re-parented into the composite component at the point indicated by this tag's placement within the section.

    So by using <cc:insertChildren> you actually move the children from the #{cc} component to the component in which you specified <cc:insertChildren>, effectively making them (great)* grandchildren of #{cc}. To get easy access to these relocated children, I use a <ui:fragment> as a parent:

    <ui:fragment binding="#{childContainer}">
        <cc:insertChildren/>
    </ui:fragment>
    

    Now you can use #{childContainer.childCount} to get to count the children you specified for your composite component. This solution is a bit fragile though: you can only use your composite component once per view, because of the binding. This problem can of course be solved by binding a FacesComponent bean to your composite component. First the bean:

    package com.stackoverflow.jsfinsertchildrenandcountexample;
    
    import javax.faces.component.FacesComponent;
    import javax.faces.component.UIComponent;
    import javax.faces.component.UINamingContainer;
    
    @FacesComponent(value = "myCompositeComponent")
    public class MyCompositeComponent extends UINamingContainer {
    
        private UIComponent childContainer;
    
        public UIComponent getChildContainer() {
            return childContainer;
        }
    
        public void setChildContainer(UIComponent childContainer) {
            this.childContainer = childContainer;
        }
    }
    

    And now you can bind this class to your composite component:

    <?xml version='1.0' encoding='UTF-8' ?>
    <ui:component
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:cc="http://java.sun.com/jsf/composite"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        >
    
        <cc:interface componentType="myCompositeComponent">
        </cc:interface>
    
        <cc:implementation>
            I have #{cc.childContainer.childCount} children.
            <ui:fragment binding="#{cc.childContainer}">
                <cc:insertChildren/>
            </ui:fragment>
        </cc:implementation>
    </ui:component>
    

    Now you have a composite component with <cc:insertChildren> and direct access to these children.

    EDIT: incorporated BalusC comment.

    0 讨论(0)
  • 2021-01-18 03:28

    Put the children in a panelGroup with an id (eg children).

    Then

    #{component.findComponent('children').childCount}
    

    will give you the correct value. Good luck!

    0 讨论(0)
  • 2021-01-18 03:32

    I had a similar problem. I switched to c:if and it worked, so in your case it would be

    <composite:implementation>
      <composite:insertChildren/>
        <c:if test="#{cc.childCount == 0}">
          some default data
        </c:if>
    </composite:implementation>
    
    0 讨论(0)
提交回复
热议问题