JSF2.0:跨多个视图保留组件状态

JSF2.0:跨多个视图保留组件状态,jsf,jsf-2,state,Jsf,Jsf 2,State,我正在使用MyFaces 2.0.3/PrimeFaces 2.2RC2开发的web应用程序分为内容区和导航区。在使用模板(即)包含在多个页面中的导航区域中,有一些小部件(例如导航树、可折叠面板等),我希望在各个视图中保留它们的组件状态 例如,假设我在主页上。当我通过单击导航树中的产品导航到产品详细信息页面时,我的Java代码使用 navigationHandler.handleNavigation(context, null, "/detailspage.jsf?faces-redirec

我正在使用MyFaces 2.0.3/PrimeFaces 2.2RC2开发的web应用程序分为内容区和导航区。在使用模板(即
)包含在多个页面中的导航区域中,有一些小部件(例如导航树、可折叠面板等),我希望在各个视图中保留它们的组件状态

例如,假设我在主页上。当我通过单击导航树中的产品导航到产品详细信息页面时,我的Java代码使用

navigationHandler.handleNavigation(context, null,
  "/detailspage.jsf?faces-redirect=true")
进入该详细信息页面的另一种方式是直接单击主页上显示的产品摘要。相应的
将引导我们进入详细信息页面

在这两种情况下,我的导航树(PrimeFaces树组件)和可折叠面板的展开状态都将丢失。我理解这是因为重定向/
h:link
会创建一个新视图

处理这个问题的最好方法是什么?我已经在我的项目中使用MyFaces Orchestral及其对话范围,但我不确定这是否有任何帮助(因为我必须将小部件的扩展/折叠状态绑定到支持bean…但据我所知,这是不可能的)。假设下一个视图中存在相同的组件,有没有办法告诉JSF哪些组件状态要传播到下一个视图

我想我需要一个指向正确方向的指针。谢谢


更新1:我刚刚尝试将面板和树绑定到会话范围的bean,但这似乎没有效果。另外,我想我必须手动绑定所有子组件(如果有的话),所以这似乎不是一个好办法

更新2:将UI组件绑定到非请求范围的bean不是一个好主意(请参阅下面我在评论中发布的链接)。如果没有更简单的方法,我可能不得不按以下步骤进行:

  • 当面板折叠或树展开时,将当前状态保存在会话范围的支持bean中(!=UI组件本身)
  • 组件的状态存储在地图中。映射键是组件的唯一(希望是)相对ID。我不能在这里使用整个绝对组件路径,因为如果视图更改,父命名容器的ID可能会更改,假设这些ID是以编程方式生成的
  • 构建新视图后,立即从映射中检索组件的状态并将其应用于组件。例如,对于面板,我可以将
    collapsed
    属性设置为从会话范围的支持bean检索到的值
更新3:我让它如上所述工作。总之,解决方案是将相关属性存储在会话作用域bean中,而不是将整个UIComponent会话作用域化。然后,在导航完成后重新构建组件时,通过检索保存的属性(使用EL)来设置属性值,例如



(这是一个简化的示例。因为我使用多个面板,所以我使用映射来存储这些属性,如上所述)。

一个解决方案是使用会话范围的bean。

可折叠面板是什么意思?我这样问是因为有一个组件是可关闭的,也有一个组件。我正在项目的导航窗格中使用。面板有一个名为“activeIndex”的属性。以下是我在sessionBean中为维护手风琴选项卡的状态所做的操作:

 private int tabIndex; //declared a private variable

    public SessionBean() {
       tabIndex = 100; //set the initial tab index to 100 so all tabs are closed when page loads.
    }

    public int getTabIndex(){
       return tabIndex;
    }

    public void setTabIndex(int tabIndex){
       this.tabIndex=tabIndex;
    }

in my navigation pane:



<p:accordionPanel activeIndex="#{sessionBean.tabIndex}" collapsible="true" autoHeight="false">
    <p:tab title="#{tab1_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" /><br/>
    </p:tab>
    <p:tab title="#{tab2_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" />
    </p:tab>
    <p:tab title="#{tab3_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" />
    </p:tab>
 </p:accordionPanel>
private int tabIndex//声明了一个私有变量
公共会话bean(){
tabIndex=100;//将初始选项卡索引设置为100,以便在加载页面时关闭所有选项卡。
}
public int getTabIndex(){
返回索引;
}
公共void setTabIndex(int-tabIndex){
this.tabIndex=tabIndex;
}
在我的导航窗格中:


我没有使用树组件进行导航,因为这给我的项目带来了一些困难,这些困难可以通过使用accordionPanel轻松克服,因此我不能谈论导航的这一部分。

将UI组件绑定到会话范围的bean是不可行的。这会在我刷新页面时导致一个非法状态异常:
组件ID j_idt12:j_idt13:j_idt14已在视图中找到。
更正:我刚刚用一个独立面板再次测试了它,现在它正在工作。现在让我们找出为什么它不能与我的其他面板一起工作……好吧,那么将组件绑定到会话范围的bean显然是不可能的。请参阅和:“为了避免组件和bean之间的生命周期不匹配,存储组件绑定的任何bean都必须是请求范围的。”通过仅保存会话范围bean中的相关属性(而不是使整个UIComponent会话范围化),使其工作。请参阅上面我的更新。对于“可折叠面板”,我指的是常规的
实例。因此,我的面板解决方案与您的类似,即从会话范围的支持bean中检索
折叠的
值:
。这里唯一的区别是,您还需要一个切换监听器来更新支持bean中的折叠状态,因为否则折叠操作将不会传播到服务器端(因为它是客户端JavaScript);在这里,您需要选择、展开和折叠侦听器来维护服务器端的状态,而不是切换侦听器。在这些侦听器中,只需更新树节点(例如
treeNode.setExpanded(true)
)即可将客户端状态传播到服务器。下次在重新加载页面时重新构建树时,树节点中的这些值将用于初始化新树。但是,我应该注意到,在PrimeFaces 2.2RC2中,expand和colla
 private int tabIndex; //declared a private variable

    public SessionBean() {
       tabIndex = 100; //set the initial tab index to 100 so all tabs are closed when page loads.
    }

    public int getTabIndex(){
       return tabIndex;
    }

    public void setTabIndex(int tabIndex){
       this.tabIndex=tabIndex;
    }

in my navigation pane:



<p:accordionPanel activeIndex="#{sessionBean.tabIndex}" collapsible="true" autoHeight="false">
    <p:tab title="#{tab1_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" /><br/>
    </p:tab>
    <p:tab title="#{tab2_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" />
    </p:tab>
    <p:tab title="#{tab3_title}">
       <h:commandLink value="link here" action="target_page?faces-redirect=true" />
    </p:tab>
 </p:accordionPanel>