我正在尝试将一种简单的可自定义新闻视图页面添加到我的Web应用程序中,例如Google's one,但更简单,使用框架。每个框架对象只有其标题和要添加的URL作为其内容。
我在最新版本上使用 JSF和primefaces 。所以我的支持bean @ViewScoped
可以访问已记录的用户,该用户存储在@SessionScoped
bean中,并且该用户已加载了相应的帧。
当我尝试在@ViewScoped
bean上进行迭代时出现问题,因为我发现这样做的唯一方法是使用c:forEach
标记。这就是我的方式:
<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>
该迭代显然不适用于navegableHomeManager
bean,因为它是@ViewScoped
。因此,bean将在每次迭代中重建。我到达的解决方案使用@SessionScoped
和navegableHomeManager
之间的另一个loggedBean
bean,这样就可以将帧存储在那里,我可以正确地访问它们进入迭代。这与上面的代码一起使用。
但是,我不认为每次我想以这种方式迭代时都必须使用@SessionScoped
bean(为每个案例创建一个特定的bean)。 这就是我尝试使用组件来避免迭代的原因。
<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>
当bean为@ViewScoped
或@SessionScoped
时,它既不起作用,因为即使设置了frame属性,ui:include
标记也已构建,没有目标路径,所以我不能在dinamically渲染目标路径。我认为,当ui:include
与c:forEach
同时应用时,使用c:forEach
标记实际上是唯一可以通过此标记的方法。
汇集您的想法。
更新
在这里,我发布了更多 xhtml 代码,以帮助理解上下文。新页面已集成到模板中。这是目标页面( /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>
这就是我尝试这样做的方式,但没有让c:forEach
代码生效:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/system/home/index.xhtml</param-value>
</context-param>
这就是支持bean标题:
@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
答案 0 :(得分:6)
坚持<c:forEach>
。它完成了你正在寻找的工作。 <ui:include>
在视图构建时运行,因此迭代标记也应在视图构建期间运行。
关于@ViewScoped
bean问题,你有两个选择:
关闭特定视图的部分状态保存:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/news.xhtml</param-value>
</context-param>
将其更改为@RequestScoped
bean并使用<f:param>
和@ManagedProperty
按请求参数维护回发状态。
如果JSF 2.2可用,将会有第三种选择:只需升级到JSF 2.2。他们修复了视图范围内的bean和部分状态保存中的鸡蛋问题。