I just dont get it:
If I want my composite component to insert children, I use
but #{cc.childCount}
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.
Put the children in a panelGroup with an id (eg children).
Then
#{component.findComponent('children').childCount}
will give you the correct value. Good luck!
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>