I'm trying to do a kind of simple customizable news view page into my web application, like Google's one but much simpler, with frames. Each frame object simply has his title and an url to be added as its content.
I'm using JSF and primefaces, both on their newest versions. So my backing bean, which is @ViewScoped
, has access to the logged user, which is stored in a @SessionScoped
bean, and that user has his corresponding frames loaded.
Problem comes when I try to iterate it over the @ViewScoped
bean, because the only way I find to do it is with a c:forEach
tag. That's the way I do:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<h:form>
<p:panel header="Noticias">
<h:panelGrid columns="#{fn:length(navegableHomeManager._UserFrames)}"
width="100%">
<c:forEach var="frame" items="#{navegableHomeManager._UserFrames}">
<p:column>
<p:panel header="#{frame._Name}" closable="true"
style="width:95%;height:500px;" id="#{frame._Name}">
<p:ajax event="close"
listener="#{navegableHomeManager.actionFrameClosed}" />
<ui:include src="#{frame._Path}" />
</p:panel>
</p:column>
</c:forEach>
</h:panelGrid>
</p:panel>
</h:form>
That iteration obviusly does not work with navegableHomeManager
bean because it is @ViewScoped
. So the bean will be rebuilt in each of the iterations. The solution I've reached uses another @SessionScoped
bean between the navegableHomeManager
and the loggedBean
, so that way the frames are stored there and I can have access to them properly into the iteration. That's working with the code above.
However I don't think it should be compulsory to use a @SessionScoped
bean (creating an specific bean for every single case) every time I want to iterate in that way. That's why I have tried using components to avoid the iteration.
<p:dataGrid columns="#{fn:length(navegableHomeManager._UserFrames)}"
value="#{navegableHomeManager._UserFrames}" var="frame">
<p:column>
<p:panel header="#{frame._Name}" closable="true"
style="width:95%;height:500px;">
<p:ajax event="close"
listener="#{navegableHomeManager.actionFrameClosed}" />
<ui:include src="#{frame._Path}" />
</p:panel>
</p:column>
</p:dataGrid>
It doesn't work neither when the bean is @ViewScoped
or @SessionScoped
, because even the frames properties are set, the ui:include
tag has already been built with no destination path, so I can't render the destination path dinamically. I think that, as ui:include
is being applied at the same time as c:forEach
, using a c:forEach
tag is really the only way to go through this.
Pool your ideas.
UPDATE
Here I post more xhtml code to help in the understanding of the context. The new's page is integrated into a template. That's the page which is targeted (/system/home/index.xhtml):
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
template="/templates/general_template.xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<ui:define name="metadata">
<f:event type="preRenderView"
listener="#{navegableHomeManager.initialize}" />
</ui:define>
<ui:define name="general_content">
<ui:include src="/system/home/home_view.xhtml" />
</ui:define>
And that's the way I also tried to do it, but not making the c:forEach
tag to work:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/system/home/index.xhtml</param-value>
</context-param>
And that's the backing bean header:
@ManagedBean
@ViewScoped
@URLMapping(id = "home", pattern = "/home", viewId = "/system/home/index.xhtml")
public class NavegableHomeManager extends SystemNavegable {
/**
*
*/
private static final long serialVersionUID = 6239319842919211716L;
@ManagedProperty(value = "#{loggedBean}")
private LoggedBean _LoggedBean;
//More stuff
Stick to <c:forEach>
. It does the job you're looking for. The <ui:include>
runs during view build time, so the iteration tag should also run during view build time.
As to the @ViewScoped
bean problem, you've 2 options:
Turn off partial state saving for the particular view:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/news.xhtml</param-value>
</context-param>
Change it to a @RequestScoped
bean and use <f:param>
and @ManagedProperty
to maintain state across postbacks by request parameters.
There would be a third option if JSF 2.2 is available: just upgrade to JSF 2.2. They've fixed the chicken-egg problem in view scoped beans and partial state saving.
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