JSF2 composite components: are #{cc.childCount} and <composite:insertChildren/> mutually exclusive?

若如初见. 提交于 2019-12-01 16:49:21

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

Then

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

will give you the correct value. Good luck!

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.

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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!