Site Network: Personal | Professional | Photography

Technical Blog

This blog will contain content related to Java, Seam, Security, my sites and projects, as well as other technical subjects I am interested in.

Comments and questions are welcome!

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="#{backingBean.selectedItem.property}" />

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!
</a:commandLink>
 

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.

28 Responses to “Displaying and Rerendering a RichFaces ModalPanel from a commandLink”

  1. HugoZ Says:

    Hi,

    I just faced a similar problem, and used a similar solution, with a panelGrid instead of a div. I could not use any parameter in my commandLink action, I dont know how you got this working (action=”#{backingBean.setSelectedItem(item)}”). I had to call a method without parameter, and get the selectedItem from the backing bean.

    To update the modalPanel header, simply add an ID to the header outputText (or other elements), and add this ID to the rerender attribute on your commandLink :


    (…)



    Click Here!

  2. Devon Says:

    Looks like Wordpress ate some of your code there, sorry about that.

    Thanks for the info on the id in the header. Totally missed that one and it works perfectly! Thanks!

    Being able to pass params in the action is a JBoss EL feature, not available in normal EL. I’m using Seam on JBoss so it’s available for me.

  3. Richard Says:

    Hi,

    Thanks a lot for the great tip.
    I have tried using h:inputText inside the modal div , but the modal panel renders it without a value but using
    h:outputText renders the value quite correctly.
    Have you tried such a scenario?

    (am using Seam)
    Cheers

  4. Devon Says:

    Richard,

    I haven’t tried using inputText inside the modal yet. I may need to do that in the near future though. I’m not sure why it wouldn’t work though… Hmm. I’ll reply back if I am able to get it to work.

  5. Gerson Says:

    The following JSF component organization is working for me. This organization enables the controls facet in the modal panel.

    Link to invoke the modalPanel:

    <a4j:commandLink
            action="#{backingBean.setSelectedItem(item)}"
    	onclick="javascript:Richfaces.showModalPanel('editSecurityGroup',{width:450,height:470})"
    	reRender="editSecurityGroupForm">
    	<h:outputText value="#{messages['action.add']}" styleClass="linkText"/>
    </a4j:commandLink>
    

    And now the ModalPanel, same aproach as yours, in a different xhtml page:

    <ui:composition
    	xmlns="http://www.w3.org/1999/xhtml"
    	xmlns:s="http://jboss.com/products/seam/taglib"
    	xmlns:ui="http://java.sun.com/jsf/facelets"
    	xmlns:f="http://java.sun.com/jsf/core"
    	xmlns:h="http://java.sun.com/jsf/html"
    	xmlns:rich="http://richfaces.org/rich"
    	xmlns:a4j="http://richfaces.org/a4j">
    
    	<rich:modalPanel id="editSecurityGroup">
    
    		<f:facet name="header">
    				<h:outputLabel value="#{messages['maintainSecurityGroups.securityGroup']}"/>
    		</f:facet>
    
    		<f:facet name="controls">
    				<h:graphicImage value="/img/icons/xtiny/close.png" styleClass="linkImage"/>
    		</f:facet>
    
    		<h:form id="editSecurityGroupForm">
    			PLEASE PUT YOUR COMPONENTS HERE !
    		</h:form>
    
    	</rich:modalPanel>		
    
    </ui:composition>
    

    And the way I am including the modalPanel inside the main page. Note that I am using two different forms one for the main composition and one for modalPanel. The following inclusion can not be done inside the main form, because a know nested form in some broswer (i.e. Internet Explorer)

    <ui:include src="/security/dialog/editSecurityGroup.xhtml" />
    

    Hope this helps.

    Greetings from Ecuador

  6. Rich Hephner Says:

    Hi all,

    I’m having a similar problem with a datatable and stumbled across this blog. I have a rich datatable with each row as a “match” object. Each match has a “nodeId” property. I need to be able to click on each row and have that nodeId show up as part of a modalPanel.

    I’m using a rich component control to try to accomplish this:

    <rich:componentControl event="onRowClick" for="assignmentPanel" operation="show">
    	<f:param value="#{match.nodeId}" name="nodeId"/>
    </rich:componentControl>
    

    Where assignmentPanel is my modal dialog. It’s patterned after this demo:

    http://livedemo.exadel.com/richfaces-demo/richfaces/componentControl.jsf?c=componentControl

    but doesn’t work at all for a Modal. Instead of displaying the proper nodeId, it displays {nodeId} Any ideas? Thanks.

  7. Devon Says:

    Hi Rich,

    can you post the rest of your xhtml code including the modal panel? I can’t promise I’ll know the answer, but I’m happy to take a look at it!

    Devon

  8. Gerson Says:

    Hi rich,

    Tell me are you working with EntityHome components?. If it is like that, The only thing you have to do is send the corresponding param that will be the entityId in the EntityHome component. This will tell that component which component is being

    <a4j:commandLink onclick="javascript:Richfaces.showModalPanel('editSecurityGroup',{width:450,height:470})"
    			 title="#{messages['tip.editSecurityGroup']}"
    			 reRender="editSecurityGroupForm">
    		<h:outputText value="#{messages['action.edit']}" styleClass="linkText"/>
    		<s:conversationPropagation type="begin" />
    		<f:param name="securityGroupId" value="#{securityGroup.id}"/>
    	</a4j:commandLink>
    

    But, I discovered that the problem could be due to one of these things:

    The conversations are not well managed: Check the complete conversation stablished in the user transaction and the begin and end points. Usually when you have a table and after one action Edits the selected object the right place to begin the conversation is inside the action. -Check the attached post-
    Check the components order inside the panel form, If you switch the order of the form with the modalPanel components in the xhtml page that panel won’t work. That was making me nuts almost for a complete day.

    Let me know how are you going.

    Cheers

  9. David Says:

    Hi Devon,

    You mentioned that you wanted to know how to update the text inside the <f:facet&gt tag. The following code works in my web app:
    <f:facet name=”header”>
      <a4j:outputPanel ajaxRendered=”true”>
        <h:outputText value=”#{myVar}”>
      </a4j:outputPanel>
    </f:facet>

    I hope this helps.

    ~David

  10. Devon Says:

    David:

    thanks! Working on Hugo’s advice what I ended up doing is this:

    <rich:modalPanel id="pictureModal" autosized="true" zindex="2000">
    	<f:facet name="header">
    		<h:outputText id="pictureHeader" value="#{selectedImage.image.getDisplayHeading(100)}" />
    	</f:facet>
    ...
    

    and then my command link looks like this:

    <a:commandLink id="showImage"
    	action="#{selectedImage.setImage(image)}"
    	oncomplete="Richfaces.showModalPanel('pictureModal',{width:760, top:200});"
    	reRender="test,pictureHeader">
    ...
    

    Which works great! But using an a4j output panel is a cool approach as well!

    Thanks!

    Devon

  11. Chandra Says:

    I am new to JSF and had been trying to have a textbox in modalpanel which when typed should update the other textboxes in the same modalpanel. I have got sum examples in the http://livedemo.exadel.com/richfaces-demo/richfaces/support.jsf?c=support site and they seem to work perfectly. But when I place the same code in my modalPanel the server doesnt seem to understnad that there is indeed a textbox in the modalPanel. I am struggling with this for a day now and am running out of ideas. Any ideas or suggestions.

  12. Devon Says:

    @Chandra:

    can you provide your code and the errors? Either post here or just e-mail them to me: devon@digitalsanctuary.com and I’ll be happy to take a look.

    Devon

  13. Chandra Says:

    Devon ,

    I think I missed the most important point you have mentioned in your blog, that the modalPanel should be in a different jsp (or a diff form) than the parent jsp. I fixed it by creating a new JSP for the modalPanel.

    Thanks

  14. Devon Says:

    @Chandra:

    I’m glad to hear you have it working!

    Devon

  15. Chandra Says:

    I am having other issue now. Not sure if its related to this blog but I hope someone could help me.

    When I enter a value in one of the textboxes in my modalPanel, the other textboxes modalPanel needs to be updated.

    I am writing a cutomtag to loop through my hashMap and get the values for the inputText.
    my loop:index is the “key” for each loop.

    HtmlInputText inputText = getHTMLInputTextObject(context,index, bean);
    HtmlAjaxSupport ajaxSupport = getAjaxSupport(context,index, bean);
    
    protected HtmlInputText getHTMLInputTextObject(FacesContext fc,
    			String index, MyPresenceBean myPresence) {
    
    		HtmlInputText inputText = new HtmlInputText();
    
    		inputText.setId(index);
    		String value = (String) myPresence.getSelectedUoms(index).toString(); // gets the value for the key
    		String bind = "#{serviceRegBean.myPresence.uoms[" + index + "]}"; //uoms is my hashMap
    		inputText.setValueBinding("value", fc.getApplication().createValueBinding(
    				bind));
    	    inputText.setValue(value);
    		return inputText;
    
    	}
    

    This code doesnt call the onkeyUp event of the a4j support when I have a valueBinding in the InputText. So when I type in the textBox no event is called.

    When I change the code for the getHTMLInputTextObject to

    protected HtmlInputText getHTMLInputTextObject(FacesContext fc,
    			String index, MyPresenceBean myPresence) {
    
    		HtmlInputText inputText = new HtmlInputText();
    
    		inputText.setId(index);
    		String value = (String) myPresence.getSelectedUoms(index).toString();
    
    	    inputText.setValue(value);
    		return inputText;
    
    	}
    

    This seem to be working perfectly but I cant really bind the value to the bean this way.

    Why doesnt the HTMLAJAXSupport event get called when we have ValueBinding for the inputtext? Hope I am making sense.

  16. Devon Says:

    @Chandra:

    Now you have me stumped:) I have no idea what to advise. Maybe someone else who reads this blog will..

    Devon

  17. Chandra Says:

    I think I found my way again with this. I created a collection of NameValuePairs and looping through them in the JSP with dataGrid.

    But yeah in my 2 days with JSF, I have learned the tweaks.

    Thanks..

  18. anut Says:

    Gerson you save my life man!!! By your post, I could solve my disappointing problem with modal panes. wowww..

  19. halley Says:

    I am trying to use a modal panel wich has a lot of data to display… no matter what i try half of the panel is cut off the other half is below the page, I can drag it up to see everything. My only best guess is that it automatically centers the panel in the middle of the screen. This would be great if I only have a little bit of info. Does anyone know what I am doing wrong? How do I get it load in the position of the screen I want?

  20. Devon Says:

    @Halley:

    If the problem is that the modal is too big for the screen, this helps:

    I put these two script tags near the bottom of my rich:modalPanel:

    <script>   document.getElementById('imageDisplayArea').style.height=f_clientHeight()-100+'px'  </script>
         <script>document.body.onresize = function (){     document.getElementById('imageDisplayArea').style.height=f_clientHeight()-100+'px'}</script>
    

    just replace “imageDisplayArea” with a the main div containing the rich modal contents. This should set the modal panel size to be 100 pixels less than the client screen size, and should resize the modal when the user resizes their browser window (for browsers which throw a resize event).

    If you want a scrollbar if the data is too big for the modal, you’ll want to set the style of that containing div to:

    style="overflow:auto"
    

    If the issue that it’s appearing too low on the page, but isn’t too small, you should be able to set the location it appears at when you call showModalPanel:

    Richfaces.showModalPanel('pictureModal',{width:760, top:20});
    
  21. VJ Says:

    I am doing something very similar - using RichFaces 3.1.5 GA, but the modal panel does not get invoked. I have tried onclick, onmousedown, oncomplete etc, but nothing works. Any help would be appreciated.
    Here are the code snippets:
    Seperate xhtml file for modalpanel which contains the foll. code:
    —————–

    —————————
    To invoke from main page, I have the foll.

    Would like to get any feedback on the modal panel not coming up.
    Thanks,
    VJ

  22. Devon Says:

    VJ,

    it looks like wordpress ate your code, sorry. Please feel free to e-mail me the code directly and I will see if I can help.

    Regards,

    Devon

  23. VJ Says:

    The code did not display ( so will paste it here).
    VJ

  24. Devon Says:

    Please e-mail it to me, wordpress keeps eating it.

    devon@digitalsanctuary.com

  25. Col Says:

    I am a bit new to this and am trouble getting it working… the main reason the examples don’t work for is that I am not using seam.

    So the #{backingBean.setSelectedItem(item)} doesn’t work for me. How do I go about getting this working without seam?

    I have looked at the a4j:actionparam, but have not made this work properly.

    Any help appreciated.
    Regards
    Col

  26. Devon Says:

    @Col: Honestly I’ve never used JSF without Seam, so I can’t help you. Perhaps another blog reader can?

  27. Col Says:

    Here’s hoping :-)

  28. alan Says:

    Hello all,
    I have a question regarding modalPanel et rerendering.
    From a main page containing a richfaces dataOrderedList, a commandbutton opens up a richfaces:modalPanel containing a orderinglist(a subset of the parent collection). The desired behaviour is that a orderchange in the orderlinglist of the modalpanel updates the order of the elements in the parent page.
    Does richfaces allow that? Thanks for your help.
    Here is my code :

    .pic {
    margin-bottom: -4px;
    margin-right: 2px;
    }

    #{item.label}

    Sort selected users

    Currently Active Items

    Name
    #{items.label}

    uri (present)
    #{items.iconURI}


    Close

    Save

Leave a Reply