I have a:
<h:panelGroup />
<h:outputText value="title" />
<h:itemThatSometimesWillShow rendered="sometimes1" />
<h:itemThatSometimesWillShow rendered="sometimes2" />
<h:itemThatSometimesWillShow rendered="sometimes3" />
...many more
And I would like that, if none of the itemThatSometimesWillShow shows, the whole panel (the title, actually) does not show either.
I did try with composite component's #{cc.childCount} > 1
, but I'm not inside a composite implementation, so looks like it will always return 0
.
Any idea? (I'm searching for something with js or EL to use in rendered
attribute of the parent panelGroup)
This is achievable with EL 3.0 stream API. My initial attempt was:
<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>
However, that didn't work quite well. It unexpectedly ran into an infinite loop which ultimately ended with an OutOfMemoryError
. It appears that #{component}
EL variable still represents the previous component at the moment the rendered
attribute is consulted. This is a bit of a chicken-egg issue: the #{component}
for current component is only injected if its rendered
attribute evaluates true
.
Given that, I can see two more options: explicitly find the component by ID as below,
<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>
or let it print some CSS class which in turn does 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>
i would shortly go with this:
<h:panelGroup rendered="{bean.isSometimes()}"/>
<h:outputText value="title" />
<h:itemThatSometimesWillShow rended="{bean.isSometimes1()}" />
<h:itemThatSometimesWillShow rended="{bean.isSometimes2()}" />
<h:itemThatSometimesWillShow rended="{bean.isSometimes3()}" />
and in the bean:
public boolean isSometimes()
{
return isSometimes1() || isSometimes2() || isSometimes3();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With