7

我只是不明白:如果我希望我的复合组件插入子组件,我会使用 <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>

有什么想法/解决方法吗?

4

3 回答 3

5

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

然后

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

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

于 2011-06-16T22:27:55.050 回答
3

来自 cc:insertChildren 文档:

使用页面中复合组件标记内的任何子组件或模板文本将在该标记在该部分中的位置指示的点处重新设置为复合组件的父级。

因此,通过使用<cc:insertChildren>,您实际上将子组件从#{cc}组件移动到您指定的组件,从而<cc:insertChildren>有效地使它们成为#{cc}. 为了轻松访问这些重新安置的孩​​子,我使用 a<ui:fragment>作为父母:

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

现在您可以使用#{childContainer.childCount}get 来计算您为复合组件指定的子级。但是这个解决方案有点脆弱:由于绑定,每个视图只能使用一次复合组件。这个问题当然可以通过将 FacesComponent 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;
    }
}

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

<?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>

现在您有了一个复合组件,可以<cc:insertChildren>直接访问这些子组件。

编辑:合并 BalusC 评论。

于 2015-07-24T20:37:11.767 回答
1

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

<composite:implementation>
  <composite:insertChildren/>
    <c:if test="#{cc.childCount == 0}">
      some default data
    </c:if>
</composite:implementation>
于 2012-04-26T08:46:12.177 回答