Można to osiągnąć za pomocą API strumienia EL 3.0. Moja pierwsza próba to:
<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>
Jednak to nie działało całkiem dobrze. Niespodziewanie natrafił na nieskończoną pętlę, która ostatecznie zakończyła się OutOfMemoryError
. Wygląda na to, że zmienna EL nadal zawiera poprzedni komponent w momencie skonsultowania atrybutu rendered
. To jest trochę problemu z jajkiem kurzego: #{component}
dla bieżącego komponentu jest wstrzykiwany tylko wtedy, gdy jego atrybut rendered
ocenia true
.
Biorąc pod uwagę, że widzę jeszcze dwie opcje: wyraźnie odnaleźć komponentu przez ID poniżej,
<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>
albo niech wydrukować niektóre klasy CSS, która z kolei działa display:none;
.
<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>
To, co zrobiłem na razie, dzięki! Ale czy nie ma bardziej abstrakcyjnego sposobu? –
Mogę tylko pomyśleć o tym, co BalusC napisał już tutaj. :) –