JSF 2.0: Preserving component state across multiple views

Posted by tlind on Stack Overflow See other posts from Stack Overflow or by tlind
Published on 2011-01-05T15:26:11Z Indexed on 2011/01/05 22:53 UTC
Read the original article Hit count: 266

Filed under:
|
|

The web application I am developing using MyFaces 2.0.3 / PrimeFaces 2.2RC2 is divided into a content and a navigation area. In the navigation area, which is included into multiple pages using templating (i.e. <ui:define>), there are some widgets (e.g. a navigation tree, collapsible panels etc.) of which I want to preserve the component state across views.

For example, let's say I am on the home page. When I navigate to a product details page by clicking on a product in the navigation tree, my Java code triggers a redirect using

navigationHandler.handleNavigation(context, null,
  "/detailspage.jsf?faces-redirect=true")

Another way of getting to that details page would be by directly clicking on a product teaser that is shown on the home page. The corresponding <h:link> would lead us to the details page.

In both cases, the expansion state of my navigation tree (a PrimeFaces tree component) and my collapsible panels is lost. I understand this is because the redirect / h:link results in the creation of a new view.

What is the best way of dealing with this? I am already using MyFaces Orchestra in my project along with its conversation scope, but I am not sure if this is of any help here (since I'd have to bind the expansion/collapsed state of the widgets to a backing bean... but as far as I know, this is not possible). Is there a way of telling JSF which component states to propagate to the next view, assuming that the same component exists in that view?

I guess I could need a pointer into the right direction here. Thanks!


Update 1: I just tried binding the panels and the tree to a session-scoped bean, but this seems to have no effect. Also, I guess I would have to bind all child components (if any) manually, so this doesn't seem like the way to go.

Update 2: Binding UI components to non-request scoped beans is not a good idea (see link I posted in a comment below). If there is no easier approach, I might have to proceed as follows:

  • When a panel is collapsed or the tree is expanded, save the current state in a session-scoped backing bean (!= the UI component itself)
  • The components' states are stored in a map. The map key is the component's (hopefully) unique, relative ID. I cannot use the whole absolute component path here, since the IDs of the parent naming containers might change if the view changes, assuming these IDs are generated programmatically.
  • As soon as a new view gets constructed, retrieve the components' states from the map and apply them to the components. For example, in case of the panels, I can set the collapsed attribute to a value retrieved from my session-scoped backing bean.

© Stack Overflow or respective owner

Related posts about jsf

Related posts about jsf-2.0