2011-06-16 22 views
6

我只是不明白: 如果我想我的複合材料部件插入孩子,我使用<composite:insertChildren/>#{cc.childCount}總是在這種情況下返回0。另一方面,如果我不使用<composite:insertChildren/>我總是得到正確childCount沒有兒童被渲染。爲什麼會發生?JSF2複合組件:分別是#{cc.childCount}和<composite:insertChildren />是否互斥?

我想在我的組件中執行的所有操作都是在沒有孩子的情況下呈現一些「默認」面板,並且在其他情況下不會渲染它 - 行爲類似於<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> 

任何想法/解決方法?

回答

5

把孩子放在一個ID爲id的小組(如兒童)。

然後

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

會給你正確的值。祝你好運!

1

我有類似的問題。我切換到c:if和它的工作,所以在你的情況下,將

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

從CC:insertChildren文檔:在使用頁面中的複合成分標籤內

任何子組件或模板文本將在該標籤在該部分內的位置所指示的位置重新合併到複合組件中。

因此,通過使用<cc:insertChildren>你居然從#{cc}組件到您指定<cc:insertChildren>組件移動孩子,有效地使的#{cc}他們(大)*孫子。如要輕鬆訪問這些搬遷的孩子,我用一個<ui:fragment>作爲父:

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

現在你可以使用#{childContainer.childCount}去計算你的複合材料部件指定的兒童。儘管這個解決方案有點脆弱:由於綁定的原因,每個視圖只能使用一次複合組件。這個問題當然可以通過將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評論。

+1

'getFamily()'是不必要的,因爲已經在'UINamingContainer'中實現了。只有當你實現'NamingContainer'接口或者另一個'UIComponent'子類時,你才需要指定你自己。 – BalusC 2015-07-24 22:25:29

+1

我站好了。謝謝。 – 2015-07-25 12:17:14