How to create a stateful Richfaces popup
Join the DZone community and get the full member experience.
Join For FreeI use JSF and especially Richfaces for 1 year. During this year I had a few issues with Richfaces popups.
Richfaces popups had the following issues
- The popup component is stored in the components tree although it is not displayed. On some use cases, the complete popup sub tree can be stored in the tree.
- Because popups are usually displayed using javascript, there are not sync with the components tree and vice versa.
- So popups are display off when user reloads the page, that generates inconsistent state.
- A lot of popups on the same page, that significates a lot of rich:modalPanel components, increases file size and decreases readability.
- Popups don't stack easily (A calls B or B calls A mean different zindex for A and B).
One of my coworker said richfaces popup component doesn’t scale because each sort of popup requires a specific declaration. The team had create a JSF fragment file that contains all the popup components whatever their domains or the business logic location in package and module.
My opinion is that a popup should be part of the UI logic. It should not be a component you add like a textbox but it would rather be a window you create with a createPopup method.
Ok let's try to improve popup logic.
First step : Java logic
The first step is to create a popup controller which manage the active popups displayed on the page. The controller is a session bean named popupController that can be wired to any controllers.The interface will be :
public interface IPopupController {The add method will be used to add and display popup.
void add(String uri, IPopupBean bean);
void removeLast();
List<IPopupDescriptor> getPopups();
UIComponent getPopupContainer();
void setPopupContainer(UIComponent popupContainer);
}
The following example will display the popup foo.xhtml with the bean fooBean:
popupController.add("foo.xhtml" , fooBean);
Second step : UI logic
The second step is to create the UI logic that will display the popups. This is a simple JSF fragment that contains the UI logic:<a4j:outputPanel binding="#{popupController.popupContainer}" id="popupContainer">
<c:forEach items="#{popupController.popups}" var="popup">
<f:subview id="popupView#{popup.id}">
<ui:include src="#{popup.uri}">
<ui:param name="popupBean" value="#{popup.popupBean}"/>
</ui:include>
</f:subview>
</c:forEach>
</a4j:outputPanel>
The popups are contained in a <a4j:outputPanel> to allow AJAX refresh. The facelet iterates on the popups managed by the popupController bean. Each popup is in a subview with a custom id to avoid duplicate id exception.
The previous fragment had to be included in all pages that used popups :
<ui:include src="/popup/popup.xhtml"/>With facelet it is easy to create a page template that will hold this fragment.
To simplify the article it's the user responsibility to create the popup file that should respect the following template :
<rich:modalPanel id="anId" zindex="#{popupBean.popupDescriptor.zIndex}">The zIndex is computed automatically by the popupController. The javascript ensures at each Ajax refresh or page reload that all popups will be redisplayed.
[...]
</rich:modalPanel>
<a4j:outputPanel>
<script type="text/javascript">
javascript:Richfaces.showModalPanel('anId')
</script>
</a4j:outputPanel>
Finally
With the following article, I show how to improve popup logic that keeps client and server sync. The drawback of this method is it needs a request to be sync with the server. On a low latency network it should not be an issue. But on a medium or high latency it may be different.I have attached a small Maven war project that contains the code of this article.
What is your opinion ?
Opinions expressed by DZone contributors are their own.
Comments