Primeface要显示多个动态内容面板

时间:2013-01-25 08:37:28

标签: jsf jsf-2 primefaces

我正在尝试将一种简单的可自定义新闻视图页面添加到我的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将在每次迭代中重建。我到达的解决方案使用@SessionScopednavegableHomeManager之间的另一个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:includec: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

1 个答案:

答案 0 :(得分:6)

坚持<c:forEach>。它完成了你正在寻找的工作。 <ui:include>在视图构建时运行,因此迭代标记也应在视图构建期间运行。

关于@ViewScoped bean问题,你有两个选择:

  1. 关闭特定视图的部分状态保存:

    <context-param>
        <param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
        <param-value>/news.xhtml</param-value>
    </context-param>
    
  2. 将其更改为@RequestScoped bean并使用<f:param>@ManagedProperty按请求参数维护回发状态。

  3. 如果JSF 2.2可用,将会有第三种选择:只需升级到JSF 2.2。他们修复了视图范围内的bean和部分状态保存中的鸡蛋问题。