RichFaces Modal Panels, s:graphicImage, and IE6

If, like me, you are using the Seam s:graphicImage tag to serve an image from within a RichFaces modal panel, you may have run into an issue where in IE6 the image does not get displayed, and you get the dreaded red X of failure. It works fine in all other browsers, including IE7, and works outside of the modal panel, but not from within the modal panel.

It’s not a problem with the image data (saving the image from another browser and serving it up directly works fine. I suspect it’s a delay issue with the rendering of the modal panel. For me, it was serving up the red X about 90% of the time under IE6.

The “fix” is to stop using the s:graphicImage tag within the modal, and use a Servlet to stream out the image data instead. It’s pretty easy.

One gotcha I had was that I already had a Servlet handling video output, and I couldn’t find an example of how to configure two separate paths into the seam web:context-filter Servlet Filter (which allows access to Seam components, like the entity manager to load up the video/image items). A helpful response on the forums gave me this solution:

Also, if you’re struggling to figure out what a library’s new feature isn’t working for you, no matter how many permutations of the documented usage you try, check the versions in the manifest files in the library’s jars. Maybe, like me, you upgraded the jars in one project, but forgot to upgrade them in this one….

Displaying and Rerendering a RichFaces ModalPanel from a commandLink

Let’s say that when a user clicks on something, perhaps selecting something from a DataTable or DataGrid, you want to call some server side code, and then popup a modal panel which needs to show content based on the new state setup by your server side call. In my case I have a DataGrid showing a number of items, and when a user clicks on an item I want to set the current selected item on a Seam component on the server, and then popup a modal panel to display detailed information about the item, and provide the user some actions within the modal panel.

Looking at the solution it seems so simple, but for some reason it took me hours of trying different combinations, orders, tags, JavaScripts, etc… before I could get this to work correctly. I had the panel appearing with the old data, or appearing with the old data and then disappearing completely, only to show the so called new data the next time I clicked on an item, or rendering on the page itself below the footer, or not popping up at all, or popping up with null data, or…. So I’m posting it up here for myself and anyone else who runs into issues.

First, create your modal panel (rich:modalPanel). I do this in a separate .xhtml file, as I will use the same model panel in various pages throughout the site. In your modal-panel.xhtml file (or whatever you choose to name it), start with a <ui:composition> tag, define your RichFaces xml namespace (and any other JSF libs you’ll be using), and then setup your <rich:modalpanel>

You need to give the modalPanel a unique id, in this case we’ll call it “myModalPanel”.

<rich:modalpanel id="myModalPanel" autosized="true" zindex="2000">

Inside your modalPanel tag, you need to define an inner div. This is the div which you will be rerendering after the server action is complete. I use tags, as I’m using Seam. Ensure that any references to backing beans or data that you want refreshed are within these div tags. You must give this div a unique id as well, in this case we’ll call it “myModalDiv”.

<s:div id="myModalDiv">

The one limitation that I’ve run into here, and if you know how to solve this, please let me know, is that the <f:facet> tags for your header text and controls can’t be inside this div, and you can’t put the div around the whole modalPanel (or it makes the panel disappear when you rerender). As such you can’t make anything from the <f:facet>s be updated on rerender. This is preventing me from having the modal panel header displaying the current selected item’s name. Not great, but not the end of the world.

So inside this div you have your dynamic output. I have lots of <h:outputtext value="#{}"> type entries in mine.

On your actual page where you will be displaying the modal panel from you need to include the modal-panel.xhtml file, I use a:

<a:include viewid="/modal-panel.xhtml">

Then, I have my page, which includes a rich:dataGrid, and inside it has an <a:commandLink> which creates the AJAX clickable item. This commandLink has to call the backend action, display the modal panel, and rerender your div.

<a:commandlink id="showItem" action="#{backingBean.setSelectedItem(item)}" oncomplete="Richfaces.showModalPanel('myModalPanel',{width:550, top:200});" rerender="myModalDiv">
Click Here!

This makes the panel display, and then the new content is rendered in the panel. It seems to work just how I wanted it to. With the minor annoyance of having to use a static modalPanel header.