2016-06-03 15 views
6

Ich habe ein:Wie rendert man eine JSF-Komponente nur, wenn mindestens zwei Kinder gerendert werden (Titel + Element)?

<h:panelGroup /> 
    <h:outputText value="title" /> 
    <h:itemThatSometimesWillShow rended="sometimes1" /> 
    <h:itemThatSometimesWillShow rended="sometimes2" /> 
    <h:itemThatSometimesWillShow rended="sometimes3" /> 
    ...many more 

Und ich würde mir gefallen, wenn keiner der itemThatSometimesWillShow zeigt, ist die ganze Platte (der Titel, tatsächlich) ist entweder nicht zeigen.

Ich habe mit Composite-Komponente #{cc.childCount} > 1 versucht, aber ich bin nicht in einer Composite-Implementierung, so sieht aus wie es wird immer 0 zurückgeben.

Irgendeine Idee? (ich bin auf der Suche nach etwas mit js oder EL in rendered Attribut des Mutter panelGroup verwenden)

Antwort

2

i kurz mit dieser gehen würde:

<h:panelGroup rendered="{bean.isSometimes()}"/> 
    <h:outputText value="title" /> 
    <h:itemThatSometimesWillShow rended="{bean.isSometimes1()}" /> 
    <h:itemThatSometimesWillShow rended="{bean.isSometimes2()}" /> 
    <h:itemThatSometimesWillShow rended="{bean.isSometimes3()}" /> 

und in der Bohne:

public boolean isSometimes() 
{ 
    return isSometimes1() || isSometimes2() || isSometimes3(); 
} 
+1

Das habe ich für jetzt getan, danke! Aber gibt es keinen abstrakteren Weg? –

+0

Ich kann nur daran denken, was BalusC hier schon geschrieben hat. :) –

4

Dies ist mit EL 3.0 Stream API erreichbar. Mein erster Versuch war:

<h:panelGroup rendered="#{component.children.stream().filter(c -> c.rendered).count() gt 1}"> 
    <h:outputText value="title" /> 
    <h:panelGroup rendered="#{false}">item1</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item2</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item3</h:panelGroup> 
</h:panelGroup> 

jedoch, dass nicht ganz gut funktionierte. Es lief unerwartet in eine Endlosschleife, die schließlich mit einer OutOfMemoryError endete. Es scheint, dass die #{component} EL-Variable immer noch die vorherige Komponente in dem Moment darstellt, in dem das Attribut rendered herangezogen wird. Dies ist ein bisschen ein Hühnerei Problem: die #{component} für aktuelle Komponente wird nur injiziert, wenn sein rendered Attribut true wertet.

Da kann ich zwei weitere Optionen: explizit die Komponente von ID finden, wie unten,

<h:panelGroup id="foo" rendered="#{component.findComponent('foo').children.stream().filter(c -> c.rendered).count() gt 1}"> 
    <h:outputText value="title" /> 
    <h:panelGroup rendered="#{false}">item1</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item2</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item3</h:panelGroup> 
</h:panelGroup> 

oder lassen Sie es einige CSS-Klasse drucken, die wiederum ein display:none; tut.

<h:panelGroup styleClass="#{component.children.stream().filter(c -> c.rendered).count() gt 1 ? 'show' : 'hide'}"> 
    <h:outputText value="title" /> 
    <h:panelGroup rendered="#{false}">item1</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item2</h:panelGroup> 
    <h:panelGroup rendered="#{false}">item3</h:panelGroup> 
</h:panelGroup> 
+1

Großartig! Ich denke: Gibt es keine Methode wie 'component.children.size()'? Ich werde danach suchen ... –

+1

Yup, genau das, oder '# {component.childCount}' für mehr Effektivität. Es ist nur nicht hilfreich bei der Lösung Ihres spezifischen Problems, da es nicht das gerenderte Attribut der Kinder berücksichtigt. – BalusC