本文介绍了仅当打开Tab时,才如何延迟加载与p:Tab中包含的页面关联的ManagedBean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个p:tabViewp:accordionPanel,并且使用ui:include在每个p:tab中包含Facelets.
我的问题是,与每个包含的页面关联的ManagedBeans会在启动时初始化,如何仅在打开特定的Tab时如何对其进行初始化.
这是代码示例:index.xhtml

I have a p:tabView or p:accordionPanel and Facelets included in each p:tab using ui:include.
My Problem is ManagedBeans associated with each included page are Initialized on starting itself, How can I make them Initialize only when the particular Tab is opened.
Here is the code Sample:index.xhtml

<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

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

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

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

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}是在加载index.xhtml本身时初始化的.默认打开的选项卡是Tab1,因此很明显#{bean1}已加载,但为什么#{bean2} ??
我发布此问题的主要原因是在Tabs之间传输数据,因此,如果有其他替代方法,请提出建议.

In the above example #{bean1} and #{bean2} are initialized on loading index.xhtml itself.
Default tab opened is Tab1 so it is obvious that #{bean1} is loaded but why #{bean2} ??
The main reason I'm posting this question is to transfer the data between Tabs, So if there is any alternative way is there then please suggest me.

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

*Using : Primfaces 3.5 and JSF 2.*1

推荐答案

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

If you want the tab contenet to be lazily loaded, why not follow the pattern that is at least provided in the showcase example (the same applies to <p:tabView>)? To repeat that example (note dynamic="true" attribute):

<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.同样会发生在例如:

As to the reason, when JSF component tree is being built, all the included page content end up in that tree, so the corresponding beans are initialized. The same will happen in e.g.:

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

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

In the above code the content will be included in JSF component tree (view build time), but will not be included in HTML DOM tree (view render time) despite the fact that the panel group will never be rendered, as view is being built (<ui:include> taghandler) at a lifecycle event prior to when it is being rendered (rendered attribute). Likewise, the following snippet yields the desired effect, as both <c:if> and <ui:include> are taghandlers:

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


最终,如果PrimeFaces <p:accordionPanel>决定在视图渲染时渲染什么内容,则也会评估视图构建时标签(这是您的情况),因此您可以强制仅在选项卡为通过包含小的<c:if>测试进行了更改.启动示例:


Ultimalely, if PrimeFaces <p:accordionPanel> decides what to render at view render time, view build time tags will be evaluated as well (which is your case), so you can force the evaluation of taghandlers to happen only when the tab is changed by including a small <c:if> test. The kickoff example:

<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>

这篇关于仅当打开Tab时,才如何延迟加载与p:Tab中包含的页面关联的ManagedBean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-02 02:22