A pretty normal case:
We have a 'portlet' composite component that has two states: expanded and collapsed. Portlets start as expanded, but user can collapse them by clicking on them. This state should be saved to the session, so that once the user refreshes the page or navigates to a new, the portlets remember if they are expanded/collapsed.
This is the core of the problem: How would you actually implement such state-saving into a component, that can be inserted on page multiple times?
Some background / ideas:
Implementing state-saving for one portlet would be easily achieved by using a session-scoped bean. Also fixed number of portlets could be supported by creating a fixed number of session-scoped beans or declaring different properties into one bean. However, I don't want to even mention why those approaches is bad.
My initial idea for this was to create a Map (or some object structure) under single session bean to hold the states for all of the portlets. However, I cannot directly refer to this data from JSF (so that JSF would also update them). I considered writing a specific getter/setter to fetch/update the right value in the map, but that's not possible as there's no identifying data during the execution of getters and setters.
However, it is probably clear that I need to save the states into a session bean. I can do the state-saving pretty easily by posting a form with f:ajax
and executing a special method using listener
and the submitted data. In order to support multiple instances of component, I could use (multiple instances of) a request-scoped bean to handle each expand/collapse. However, in order to actually post the data that identifies the portlet and its' state, I need to first insert it on the form fields in render-time.
So, how to actually provide each portlet with right data on render-time (actually just state boolean/enum in this case, but consider a case where more data should be handled)?
It seems that:
h:inputHidden
andh:inputText
do not support setting initial value other than than the value-attribute (which would point to#{portletBean.portletState}
).- I cannot auto-load the request beans with right initial values on their creation time, as there's no identifying information available.
Once again it feels like I'm missing something... pointers?
I suppose at least one of the answers would be to use UIComponent
rather than composite components, but I would like to keep this as composite component as it contains lots of raw HTML elements.
Update:
- There is a rather similar question, with suggestion to use view-scoped bean. I don't think this is viable here, however.