Wednesday, December 29, 2010

How to create a stateful Richfaces popup

I 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 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 :

The zIndex is computed automatically by the popupController. The javascript ensures at each Ajax refresh or page reload that all popups will be redisplayed.

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.