Geek Lair

JSF – Richfaces Ajax Modal Dialog

with 3 comments

Creating a Richfaces Modal dialog is simple enough as explained in the Richfaces reference document. But I wanted an ajax modal dialog which will be shown on click of a link. Here is how to go about it:

My requirement is, I have a user page with an “Update Profile” link. On clicking the link, a modal dialog should popup which has a form for updating the profile.

In the user page I have a form, since a4j:commandLink element should be in a form:

<h:form id="inboxForm">
	<div id="topBar">
    	<a4j:keepAlive beanName="userBean" ajaxOnly="true"/>
		<a4j:commandLink oncomplete="#{rich:component('editPanel')}.show()" 
			reRender="editPanel" value="#{msgs.updateProfile}">
			<f:setPropertyActionListener value="#{inbox.userLogin}" 
			target="#{userBean.currentUser}"/>
		</a4j:commandLink>
    	<h:commandLink action="#{login.logout}" value="#{msgs.logout}"/>
	</div>
</h:form>

userBean has a request scope and that is why I have an a4j:keepAlive element so that the bean is kept alive during the ajax call.

The a4j:commandLink has a f:setPropertyActionListener element which will set a the currentUser object on userBean. After the ajax request has been made, the editPanel, which is the modal dialog, will be re-rendered. The oncomplete attribute has a JavaScript call to show the modal dialog (by default, it will be hidden).

Here is my modal panel:

<a4j:outputPanel layout="none">
	<rich:modalPanel id="editPanel" width="530"  height="320"
		rendered="#{not empty userBean.currentUser}">
		<f:facet name="header">
            <h:outputText value="#{msgs.updateProfile}" />            
        </f:facet>
        <f:facet name="controls">
            <h:panelGroup>
                <h:graphicImage value="/css/images/close.png"
                    styleClass="hidelink" id="hidelink1" />
                <rich:componentControl for="editPanel" attachTo="hidelink1"
                    operation="hide" event="onclick"/>
            </h:panelGroup>
        </f:facet>
		
		<a4j:include viewId="/profile.jsp"/>
	</rich:modalPanel>
</a4j:outputPanel>

Since the modal panel should be rendered on an ajax call, I have it enclosed in a a4j:outputPanel tag. The layout="none" means that no html tag will be rendered. If no layout is specified, a span tag will be rendered. If layout="block", a div will be rendered.

The rich:modalPanel has a rendered="#{not empty userBean.currentUser}" attribute. It means that the modal panel will be rendered only when userBean.currentUser is not null.

The modal panel has a header facet which has a title and a close icon. The form is included with an a4j:include tag. Here is the profile.jsp:

<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@taglib uri="http://richfaces.org/rich" prefix="rich"%>
<h:form id="profileForm">
<div id="profileContainer">
<a4j:outputPanel ajaxRendered="true">
	<div class="messages">
		<h:messages globalOnly="true"/>
	</div>
	<fieldset>			
	    <ul>
		<li>
		    <h:outputLabel value="#{msgs.firstName}" for="fname"/>
		    <div class="innerList">
			<ul>
			    <li>
				<h:inputText id="fname" 
				value="#{userBean.currentUser.userDetails.firstName}"
				maxlength="30">
				    <f:validateLength maximum="30"/>
				</h:inputText>
			    </li>
			    <li id="fnameErr" class="hidden">
				<h:message for="fname" errorClass="error" />
			    </li>
			</ul>
		    </div>				    
		</li>
		<li>
		    <h:outputLabel value="#{msgs.lastName}" for="lname"/>
		    <div class="innerList">
			<ul>
			    <li>
				<h:inputText id="lname" 
				value="#{userBean.currentUser.userDetails.lastName}"
				maxlength="30">
				    <f:validateLength maximum="30"/>
				</h:inputText>
			    </li>
			    <li id="lnameErr" class="hidden">
				<h:message for="lname" errorClass="error" />
			    </li>
			</ul>
		    </div>					
		</li>
		<li>
		    <h:outputLabel value="#{msgs.enterNewPassword}" for="pwd">
		    </h:outputLabel>
		    <div class="innerList">
			<ul>
			    <li>
				<h:inputSecret
				    id="pwd" value="#{userBean.password}" maxlength="15" redisplay="true"
				    requiredMessage="#{msgs.enterPasswordReq}">
				<f:validateLength minimum="6" maximum="15"/>
				</h:inputSecret>
			    </li>
			    <li><h:message for="pwd" errorClass="error" /></li>
			    <li id="pwdErr" class="hidden">
				<span class="error"><h:outputText value="#{msgs.enterPasswordReq}"/></span>
			    </li>
			    <li><h:outputText value="#{msgs.minPwdLenth}"/></li>
			</ul>				    
		    </div>
		</li>
		<li>
		    <h:outputLabel value="#{msgs.reenterNewPassword}" for="repwd">
		    </h:outputLabel>
		    <div class="innerList">
			<ul>
			    <li>
				<h:inputSecret
				    id="repwd" value="#{userBean.repassword}" maxlength="15" redisplay="true"
				    requiredMessage="#{msgs.reenterPasswordReq}">
					<f:validateLength maximum="15"/>
				</h:inputSecret>
			    </li>
			    <li><h:message for="repwd" errorClass="error" /></li>
			    <li id="repwdErr" class="hidden">
				<span class="error"><h:outputText value="#{msgs.reenterPasswordReq}"/></span>						
			    </li>
			</ul>				    
		    </div>				    
		</li>
		<li>
		    <h:outputLabel value="#{msgs.emailAddr}" for="email">
			<span class="redText">*</span>
		    </h:outputLabel>
		    <div class="innerList">
			<ul>
			    <li>
				<h:inputText 
				    id="email" value="#{userBean.currentUser.userDetails.emailId}" maxlength="40"
				    requiredMessage="#{msgs.emailAddrReq}" required="true">
				    <f:validateLength maximum="40"/>
				</h:inputText>
			    </li>
			    <li><h:message for="email" errorClass="error" /></li>
			    <li id="emailErr" class="hidden">
				<span class="error"><h:outputText value="#{msgs.emailAddrReq}"/></span>						
			    </li>
			</ul>
		    </div>				    					
		</li>				
	    </ul>
		<div class="spacerDiv"></div>
	    <ul class="hor_li">
			<li><a4j:commandButton id="profUpdate" value="#{msgs['btn.update']}" 
				action="#{userBean.updateProfile}"/></li>
			<li><a4j:commandButton id="profCancel" value="#{msgs['btn.cancel']}" 
				oncomplete="#{rich:component('editPanel')}.hide();"/></li>
		</ul>
	</fieldset>
</a4j:outputPanel>						
</div>
</h:form>

The profile form has two a4j:commandButton elements. One for submitting the form data and the other for closing the modal dialog. The form submission is through ajax and any validation errors are shown after the server responds to the ajax call.

Advertisements

Written by anonir

February 13, 2010 at 14:57

Posted in JEE, Web

Tagged with , ,

3 Responses

Subscribe to comments with RSS.

  1. I have been using modalPanel and I ran into a few issues. At first I tried it with show and hide links and IE would open the dialog but wouldn’t close it. If I set IE to compatibility mode it would close it. (IE 8) IE actually shows an error and the error is “not implemented”.
    Firefox/Chrome, no problem.
    So in my dialog I have it set to a showWhenRendered of a boolean from my bean and the command button calls a method in the bean that changes that boolean to false and it lists itself in the rerender list. The commandbutton is ajaxSingle=”true” and so I get around IE not working that way.

    Hope this helps.

    Mike

    October 5, 2010 at 02:00

    • @Mike, thanks for sharing your IE workaround.

      anonir

      October 5, 2010 at 11:07

  2. last version richfaces,,, menos problemas con navegadores

    Diego A.

    December 23, 2010 at 21:55


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: