我使用p:tabView
在每个p:accordionPanel
中包含p:tab
或ui:include
和Facelets。
我的问题是与每个包含页面关联的ManagedBeans在启动时初始化,如何在打开特定选项卡时使它们初始化。
这是代码示例:
的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
<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}
在加载index.xhtml
时自动初始化。
打开默认选项卡是Tab1,因此很明显加载了#{bean1}
,但为什么#{bean2}
?
我发布这个问题的主要原因是在Tabs之间传输数据,所以如果有任何替代方式,那么请建议我。
*使用:Primfaces 3.5和JSF 2. * 1
答案 0 :(得分:2)
如果您希望延迟加载制表符竞争,为什么不遵循showcase example中至少提供的模式(同样适用于<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>
taghandler)之前的生命周期事件(rendered
属性)。同样,以下代码段会产生预期效果,因为<c:if>
和<ui:include>
都是标记处理程序:
<c:if test="#{bean.tab eq 1}">
<ui:include src="page1.xhtml"/>
</c:if>
Ultimalely,如果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>