问题
I'm iterating over a list of items in composite component. I want to expose each item of the list so that they could be used within the child component of this composite component, to create a template for how to display all items in the list.
Here is my Composite Component implementation:
customList.xhtml
<ui:component
xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:ui="http://java.sun.com/jsf/facelets">
<cc:interface>
</cc:interface>
<cc:implementation>
...
...
<ui:repeat value="#{listRetriever.list}" var="item">
<cc:insertChildren />
</ui:repeat>
</cc:implementation>
</ui:component>
Now I want to make use of #{item}
while defining the child component of composite component in my page (similar to h:dataTable
or ui:repeat
).
<my:customList>
#{item} <!--- over here--->
</my:customList>
回答1:
That won't work with <cc:insertChildren>
inside <ui:repeat>
as the <cc:insertChildren>
is evaluated during view build time, not during view render time. The #{item}
is only available during view render time as the <ui:repeat>
runs during view render time only.
It'll work when you use JSTL <c:forEach>
instead as it's also evaluated during view build time like the <cc:insertChildren>
itself.
xmlns:c="http://java.sun.com/jsp/jstl/core"
...
<c:forEach items="#{listRetriever.list}" var="item">
<cc:insertChildren />
</c:forEach>
Be careful when you use the composite in turn inside another repeating JSF component, it wouldn't work then. See also JSTL in JSF2 Facelets... makes sense?.
An alternative, apart from creating a custom component which extends UIData
or UIRepeat
, is using <ui:decorate>
instead.
First make customList.xhtml
a normal template:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
...
...
<ui:repeat value="#{list}" var="item">
<ui:insert name="item" />
</ui:repeat>
...
...
</ui:composition>
Then you can use it as follows:
<ui:decorate template="customList.xhtml">
<ui:param name="list" value="#{bean.list}" />
<ui:define name="item">
#{item}
</ui:define>
</ui:decorate>
回答2:
These days I've tried to do something similar, unresolved.
My solution, the value of the var attribute on my own compononent never can do it configurable. So stay fixed under the name "var", and always expose to my component and I use the variable "var".
Example of mi code:
Component: file:listadoPaginado.xhtml
<composite:interface>
<composite:attribute name="id" required="true"
displayName="ID if component"
shortDescription="ID of component" />
<composite:attribute name="value" required="true"
displayName="List with values to iterate"/>
</composite:interface>
<!-- Implementacion de la estructura del componente -->
<composite:implementation>
<h:panelGroup id="#{cc.attrs.id}_panel_comp">
<br/>
<div style="#{cc.attrs.style}">
<ui:repeat var="var" value="#{cc.attrs.value.model}">
<composite:insertChildren/>
</ui:repeat>
</div>
</h:panelGroup>
</composite:implementation>
Use of Component:
<gb:listadoPaginado id="listado_garantias"
value="#{beanTest.myList}">
<p:panel>
<p:panelGrid>
<p:row>
<p:column>
<h:outputLabel value="#{var.description}"/>
</p:column>
<p:column>
<p:inputText value="#{var.longDescription}"/>
</p:column>
</p:row>
</p:panelGrid>
</p:panel>
来源:https://stackoverflow.com/questions/11071413/expose-items-of-a-list-while-iterating-within-composite-component