'How to render a JSF component only if at least two children are rendered (title + item)?
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)
Solution 1:[1]
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>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
