JSF2复合组件:#{cc.childCount}和<composite:insertchildren>是互斥的吗?</composite:insertchildren>

时间:2011-06-16 19:36:46

标签: jsf jsf-2 composite-component

我只是不明白: 如果我希望我的复合组件插入子组件,我使用 <composite:insertChildren/>#{cc.childCount}在这种情况下始终返回0。另一方面,如果我不使用 <composite:insertChildren/>我总是会在没有孩子被渲染的情况下得到正确的childCount。为什么会这样?

我想在我的组件中做的就是在没有子节点的情况下渲染一些“默认”面板,在其他情况下不渲染它 - 行为类似于<ui:insert name="param_name">default value</ui:insert>。所以我需要insertChildren和childCount,它们似乎不能一起工作。

以下是代码:

<my:test>
  <h:outputText value="child1" rendered="#{some.trueValue}"/>
  <h:outputText value="child2" rendered="#{some.trueValue}"/>
<my:test>

如果我使用下面的实现,我会按预期呈现2

<composite:implementation>
  <h:outputText value="#{cc.childCount}"/> 
</composite:implementation>

使用insertChildren时,我会让两个孩子都呈现,0最后:

<composite:implementation>
  <composite:insertChildren/>
  <h:outputText value="#{cc.childCount}"/> 
</composite:implementation>

我的目标是:

<composite:implementation>
  <composite:insertChildren/>
  <h:panelGroup rendered="#{cc.childCount == 0}">
    some default data
  </h:panelGroup> 
</composite:implementation>

任何想法/解决方法?

3 个答案:

答案 0 :(得分:5)

将孩子放在带有id的panelGroup中(例如孩子)。

然后

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

会给你正确的价值。祝你好运!

答案 1 :(得分:3)

来自cc:insertChildren文档:

  

使用页面中复合组件标签内的任何子组件或模板文本都将在该标签在该部分中的位置所指示的位置重新组合到复合组件中。

因此,通过使用<cc:insertChildren>,您实际上将孩子从#{cc}组件移动到您指定<cc:insertChildren>的组件,从而有效地使他们(伟大)* {{1}的孙子}。为了方便访问这些重新定位的孩子,我使用#{cc}作为父母:

<ui:fragment>

现在,您可以使用<ui:fragment binding="#{childContainer}"> <cc:insertChildren/> </ui:fragment> 来计算为复合组件指定的子项。这个解决方案有点脆弱:由于绑定,每个视图只能使用一次复合组件。当然可以通过将FacesComponent bean绑定到复合组件来解决此问题。首先是豆子:

#{childContainer.childCount}

现在您可以将此类绑定到复合组件:

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;
    }
}

现在,您拥有一个包含<?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> 的复合组件,可以直接访问这些子组件。

编辑:纳入BalusC评论。

答案 2 :(得分:1)

我有类似的问题。我切换到c:if并且它有效,所以在你的情况下它将是

<composite:implementation>
  <composite:insertChildren/>
    <c:if test="#{cc.childCount == 0}">
      some default data
    </c:if>
</composite:implementation>