4

我在每个using中都包含一个p:tabVieworp:accordionPanel和 Facelets 。 我的问题是与每个包含的页面关联的 ManagedBeans 在启动时自行初始化,我怎样才能使它们仅在打开特定选项卡时才初始化。 这是代码示例:index.xhtmlp:tabui:include

<p:tabView dynamic="true" cache="true">
   <p:tab title="Bean 1 Page 1">
    <ui:include src="page1.xhtml"/>
   </p:tab>

   <p:tab title="Bean 2 Page 2">
    <ui:include src="page2.xhtml"/>
   </p:tab>
</p:tabView>

page1.xhtml

<h:body>
    <f:metadata>
    <f:event listener="#{bean1.bean1PreRender}" type="preRenderView"/>
    </f:metadata>
    <h:form>
    <h:outputLabel value="#{bean1.bean1Text}"/>
    </h:form>
</h:body>

Bean1.java

@ManagedBean
@ViewScoped
public class Bean1 implements Serializable{
    private String bean1Text = "Hello From Bean 1";
    public Bean1() {
        System.out.println("Bean 1 Constructor");
    }
    @PostConstruct
    public void init(){
        System.out.println("Bean 1 @PostConstruct");
    }
    public void bean1PreRender(){
            System.out.println("Bean 1 PreRender PostBack Call");
        if(!FacesContext.getCurrentInstance().isPostback()){
            System.out.println("Bean 1 PreRender NON PostBack Call");
        }
    }
    //SETTER GETTER
}

page2.xhtml

<h:body>
    <f:metadata>
    <f:event listener="#{bean2.bean2PreRender}" type="preRenderView"/>
    </f:metadata>
    <h:form>
    <h:outputLabel value="#{bean2.bean2Text}"/>
    </h:form>
</h:body>

Bean2.java

    @ManagedBean
    @ViewScoped
    public class Bean2 implements Serializable{
        private String bean2Text = "Hello From Bean 2";
        public Bean2() {
            System.out.println("Bean 2 Constructor");
        }
        @PostConstruct
        public void init(){
            System.out.println("Bean 2 @PostConstruct");
        }
        public void bean2PreRender(){
                System.out.println("Bean 2 PreRender PostBack Call");
            if(!FacesContext.getCurrentInstance().isPostback()){
                System.out.println("Bean 2 PreRender NON PostBack Call");
            }
        }
        //SETTER GETTER
    }

}

在上面的示例中#{bean1},并且在加载自身#{bean2}时被初始化。 打开的默认选项卡是 Tab1,所以很明显它已加载,但为什么? 我发布这个问题的主要原因是在选项卡之间传输数据,所以如果有任何替代方法,请建议我。index.xhtml
#{bean1}#{bean2}

*使用:Primfaces 3.5 和 JSF 2.*1

4

1 回答 1

2

如果您希望标签内容被延迟加载,为什么不遵循至少在展示示例中提供的模式(同样适用于<p:tabView>)?重复该示例(注意dynamic="true"属性):

<h:form>  
    <p:accordionPanel dynamic="true" cache="true">  
        <p:tab title="Bean 1 Page 1">
            <ui:include src="page1.xhtml"/>
        </p:tab>
        <p:tab title="Bean 2 Page 2">
            <ui:include src="page2.xhtml"/>
        </p:tab>
    </p:accordionPanel>
</h:form>

至于原因,在构建 JSF 组件树时,所有包含的页面内容最终都在该树中,因此初始化了相应的 bean。同样的情况也会发生在例如:

<h:panelGroup rendered="false">
    <ui:include src="page1.xhtml"/>
</h:panelGroup>

在上面的代码中,内容将包含在 JSF 组件树中(视图构建时间),但不会包含在 HTML DOM 树中(视图渲染时间),尽管面板组永远不会被渲染,因为正在构建视图(<ui:include>标记处理程序)在生命周期事件被渲染之前(rendered属性)。同样,以下代码段会产生所需的效果,因为两者<c:if>都是<ui:include>标记处理程序:

<c:if test="#{bean.tab eq 1}">
    <ui:include src="page1.xhtml"/>
</c:if>

最后,如果 PrimeFaces<p:accordionPanel>决定在视图渲染时渲染什么,视图构建时标签也将被评估(这是你的情况),所以你可以强制标签处理程序的评估仅在选项卡被更改时发生,包括一个小<c:if>测试. 开球示例:

<h:form>  
    <p:accordionPanel dynamic="true" cache="true">
        <p:tab title="Bean 1 Page 1">
            <c:if test="#{component.parent.activeIndex eq 0 or empty component.parent.activeIndex}">
                <ui:include src="page1.xhtml"/>
            </c:if>
        </p:tab>
        <p:tab title="Bean 2 Page 2">
            <c:if test="#{component.parent.activeIndex eq 1}">
                <ui:include src="page2.xhtml"/>
            </c:if>
        </p:tab>
    </p:accordionPanel>
</h:form>
于 2013-09-30T08:39:41.013 回答