Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

Exclusive offer: get 50% off this eBook here
JBoss RichFaces 3.3

JBoss RichFaces 3.3 — Save 50%

Enhance your JSF web applications using powerful AJAX components

$23.99    $12.00
by Demetrio Filocamo | October 2009 | Java Open Source Web Development

Read Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 1 here.

The contact detail

For the third column, we would like to show three different statuses:

The "No contact selected" message when no contact is selected (so the property is null)

A view-only box when we are not in the edit mode (the property selectedContactEditing is set to false)

An edit box when we are in the edit mode (the property selectedContactEditing is set to true)

So, let's open the home.xhtml page and insert the third column inside the panel grid with the three statuses:

<a:outputPanel id="contactDetail">
<a:outputPanel rendered="#{homeSelectedContactHelper.
selectedContact==null}">
<rich:panel>
<h:outputText
value="#{messages['noContactSelected']}"/>
</rich:panel>
</a:outputPanel>

<a:outputPanel
rendered="#{homeSelectedContactHelper.
selectedContact!=null and
homeSelectedContactHelper.
selectedContactEditing==false}">
<ui:include src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="main/contactView.xhtml"/>
</a:outputPanel>
<a:outputPanel
rendered="#{homeSelectedContactHelper.
selectedContact!=null and
homeSelectedContactHelper.
selectedContactEditing==true}">
<ui:include src='//dgdsbygo8mp3h.cloudfront.net/sites/default/files/blank.gif' data-original="main/contactEdit.xhtml"/>
</a:outputPanel>
</a:outputPanel>

Here, we have put the main a:outputPanel as the main placeholder, and inside it we put three more instances of a:outputPanel (one for every state) with the rendered attribute in order to decide which one to show.

The first one just shows a message when homeSelectedContactHelper.selectedContact is set to null:

The second instance of a:outputPanel will include the main/contactView.xhtml file only if homeSelectedContactHelper.selectedContact is not null, and we are not in editing mode (so homeSelectedContactHelper.selectedContactEditing is set to false); the third one will be shown only if homeSelectedContactHelper.selectedContact is not null, and we are in the edit mode (that is homeSelectedContactHelper.selectedContactEditing is equal to true).

Before starting to write the include sections, let's see how the main bean for the selected contact would look, and connect it with the data table for selecting the contact from it.

The support bean

Let's create a new class called HomeSelectedContactHelper inside the book.richfaces.advcm.modules.main package; the class might look like this:

@Name("homeSelectedContactHelper")
@Scope(ScopeType.CONVERSATION)
public class HomeSelectedContactHelper {

@In(create = true)
EntityManager entityManager;

@In(required = true)
Contact loggedUser;

@In
FacesMessages facesMessages;

// My code here
}

This is a standard JBoss Seam component and  now let's add the properties.

The bean that we are going to use for view and edit features is very simple to understand—it just contains two properties (namely selectedContact and selectedContactEditing) and some action methods to manage them.

Let's add the properties to our class:

private Contact selectedContact;

private Boolean selectedContactEditing;

public Contact getSelectedContact() {
return selectedContact;
}

public void setSelectedContact(Contact selectedContact) {
this.selectedContact = selectedContact;
}

public Boolean getSelectedContactEditing() {
return selectedContactEditing;
}

public void setSelectedContactEditing(Boolean selectedContactEditing) {
this.selectedContactEditing = selectedContactEditing;
}

As you can see, we just added two properties with standard the getter and setter.

Let's now see the action methods:

public void createNewEmptyContactInstance() {
setSelectedContact(new Contact());
}

public void insertNewContact() {
// Attaching the owner of the contact
getSelectedContact().setContact(loggedUser);

entityManager.persist(getSelectedContact());

facesMessages.addFromResourceBundle(StatusMessage.Severity.INFO,
 "contactAdded");
}

public void saveContactData() {
entityManager.merge(getSelectedContact());

facesMessages.addFromResourceBundle(StatusMessage.Severity.INFO,
 "contactSaved");
}

public void deleteSelectedContact() {
entityManager.remove(getSelectedContact());

// De-selecting the current contact
setSelectedContact(null);
setSelectedContactEditing(null);

facesMessages.addFromResourceBundle(StatusMessage.Severity.INFO,
"contactDeleted");
}

public boolean isSelectedContactManaged() {
return getSelectedContact() != null && entityManager.contains
(getSelectedContact());
}

It's not difficult to understand what they do, however, in order to be clear, we are going to describe what each method does.

The method createNewEmptyContactInstance() simply sets the selectedContact property with a new instance of the Contact class—it will be called by the "add contact" button.

After the user has clicked on the "add contact" button and inserted the contact data, he/she has to persist this new instance of data into the database. It is done by the insertNewContact() method, called when he/she clicks on the Insert button.

If the user edits a contact and clicks on the "Save" button, the saveContactData() method will be called, in order to store the modifications into the database.

As for saving, the deleteSelectedContact() method will be called by the "Delete" button, in order to remove the instance from the database.

A special mention for the isSelectedContactManaged() method—it is used to determine if the selectedContact property contains a bean that exists in the database (so, I'm editing it), or a new instance not yet persisted to the database. We use it especially in rendered properties, in order to determine which component to show (you will see this in the next section).

Selecting the contact from the contacts list

We will use the contacts list in order to decide which contact must be shown in the detail view.

The simple way is to add a new column into the dataTable, and put a command button (or link) to select the bean in order to visualize the detail view.

Let's open the contactsList.xhtml file and add another column as follows:

<rich:column width="10%" style="text-align: center">
<a:commandButton image="/img/view.png"
reRender="contactDetail">
<f:setPropertyActionListener value="#{contact}"
target="#{homeSelectedContactHelper.selectedContact}"/>
<f:setPropertyActionListener value="#{false}"
target="#{homeSelectedContactHelper.selectedContactEditing}"/>
</a:commandButton>
</rich:column>

Inside the column, we added the a:commandButton component (that shows an image instead of the standard text) that doesn't call any action—it uses the f:setPropertyAction method to set the homeSelectedContactHelper.selectedContact value to contact (the row value of the dataTable), and to tell to show the view box and not the edit one (setting homeSelectedContactHelper.selectedContactEditing to false).

After the Ajax call, it will re-render the contactDetail box in order to reflect the change.

Also, the header must be changed to reflect the column add:

<rich:dataTable ... >
<f:facet name="header">
<rich:columnGroup>
<rich:column colspan="3">
<h:outputText value="Contacts"/>
</rich:column>
<rich:column breakBefore="true">
<h:outputText value="Name"/>
</rich:column>
<rich:column>
<h:outputText value="Surname"/>
</rich:column>
<rich:column>
<rich:spacer/>
</rich:column>
</rich:columnGroup>
</f:facet>
...

We incremented the colspan attribute value and added a new (empty) column header.

The new contacts list will look like the following screenshot:

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

Adding a new contact

Another feature we would like to add to the contacts list is the "Add contact" button. In order to do that, we are going to use the empty toolbar.

Let's add a new action button into the rich:toolbar component:

<a:commandButton image="/img/addcontact.png"
reRender="contactDetail"
action="#{homeSelectedContactHelper.createNewEmptyContactInstance}">
<f:setPropertyActionListener value="#{true}"
target="#{homeSelectedContactHelper.selectedContactEditing}"/>
</a:commandButton>

This button will call the homeSelectedContactHelper.createNewEmptyContactInstance() action method in order to create and select an empty instance and will set homeSelectedContactHelper.selectedContactEditing to true in order to start the editing; after those Ajax calls, it will re-render the contactDetail box to reflect the changes.

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

Viewing contact detail

We are ready to implement the view contact detail box; just open the /view/main/contactView.xhtml file and add the following code:

<h:form>
<rich:panel>
<f:facet name="header">
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.name}
#{homeSelectedContactHelper.selectedContact.surname}"/>
</f:facet>
<h:panelGrid columns="2" rowClasses="prop"
columnClasses="name,value">
<h:outputText value="#{messages['name']}:"/>
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.name}"/>
<h:outputText value="#{messages['surname']}:"/>
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.surname}"/>

<h:outputText value="#{messages['company']}:"/>
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.company}"/>

<h:outputText value="#{messages['email']}:"/>
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.email}"/>
</h:panelGrid>
</rich:panel>

<rich:toolBar>
<rich:toolBarGroup>
<a:commandLink ajaxSingle="true"
reRender="contactDetail"
styleClass="image-command-link">
<f:setPropertyActionListener value="#{true}"
target="#{homeSelectedContactHelper.selectedContactEditing}"/>

<h:graphicImage value="/img/edit.png" />
<h:outputText value="#{messages['edit']}" />

</a:commandLink>
</rich:toolBarGroup>
</rich:toolBar>
</h:form>

The first part is just rich:panel containing h:panelGrid with the fields' detail. In the second part of the code, we put rich:toolBar containing a command link (with an image and a text) that activates the edit mode—it, in fact, just sets the homeSelectedContactHelper.selectedContactEditing property to true and re-renders contactDetail in order to make it appear in the edit box.

We also added a new CSS class into the /view/stylesheet/theme.css file to manage the layout of command links with images:

.image-command-link {
text-decoration: none;
}

.image-command-link img {
vertical-align: middle;
padding-right: 3px;
}

The view box looks like:

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

We are now ready to develop the edit box.

Editing contact detail

When in the edit mode, the content of the /view/main/contactEdit.xhtml file will be shown in the contact detail box—let's open it for editing.

Let's add the code for creating the main panel:

<h:form>
<rich:panel>
<f:facet name="header">
<h:panelGroup>
<h:outputText
value="#{homeSelectedContactHelper.selectedContact.name}
#{homeSelectedContactHelper.selectedContact.surname}"
rendered="#{homeSelectedContactHelper.selectedContactManaged}"/>

<h:outputText
value="#{messages['newContact']}"
rendered="#{!homeSelectedContactHelper.selectedContactManaged}"/>
</h:panelGroup>
</f:facet>

<!-- my code here -->

</rich:panel>

<!-- my code here -->

</h:form>

This is a standard rich:panel with a customized header—it has two h:outputText components that will be shown depending on the rendered attribute (whether it's a new contact or not).

More than one component inside f:facet
Remember that f:facet must have only one child, so, to put more than one component, you have to use a surrounding one like h:panelGroup or something similar.

Inside the panel, we are going to put h:panelGrid containing the components for data editing:

<rich:graphValidator>
<h:panelGrid columns="3" rowClasses="prop"
columnClasses="name,value,validatormsg">
<h:outputLabel for="scName"
value="#{messages['name']}:"/>
<h:inputText id="scName"
value="#{homeSelectedContactHelper.selectedContact.name}"/>
<rich:message for="scName" styleClass="messagesingle"
errorClass="errormsg"
infoClass="infomsg"
warnClass="warnmsg"/>

<h:outputLabel for="scSurname"
value="#{messages['surname']}:"/>
<h:inputText id="scSurname"
value="#{homeSelectedContactHelper.selectedContact.surname}"/>
<rich:message for="scSurname"
styleClass="messagesingle"
errorClass="errormsg"
infoClass="infomsg"
warnClass="warnmsg"/>

<h:outputLabel for="scCompany"
value="#{messages['company']}:"/>
<h:inputText id="scCompany"
value="#{homeSelectedContactHelper.selectedContact.company}"/>
<rich:message for="scCompany"
styleClass="messagesingle"
errorClass="errormsg"
infoClass="infomsg"
warnClass="warnmsg"/>
<h:outputLabel for="scEmail"
value="#{messages['email']}:"/>
<h:inputText id="scEmail"
value="#{homeSelectedContactHelper.selectedContact.email}"/>
<rich:message for="scEmail" styleClass="messagesingle"
errorClass="errormsg"
infoClass="infomsg"
warnClass="warnmsg"/>
</h:panelGrid>
<rich:graphValidator>

Nothing complicated here, we've just used h:outputLabel, h:inputText, and rich:message for every Contact property to be edited; it appears as follows:

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

JBoss RichFaces 3.3 Enhance your JSF web applications using powerful AJAX components
Published: October 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

The button toolbar

At the end of the panel, we would like to put the toolbar containing the action buttons for inserting, saving, canceling, and deleting the selected contact shown.

In order to do that, let's insert the following code after the rich:panel closing tag (and before the h:form closing tag):

<rich:toolBar>
<rich:toolBarGroup>

<!-- my action buttons here -->

</rich:toolBarGroup>
</rich:toolBar>

Let's start inserting the insert action buttons for a new contact:

<a:commandLink reRender="contactsList,contactDetail"
action="#{homeSelectedContactHelper.insertNewContact}"
rendered="#{!homeSelectedContactHelper.selectedContactManaged}"
styleClass="image-command-link">
<f:setPropertyActionListener value="#{null}"
target="#{homeContactsListHelper.contactsList}"/>

<h:graphicImage value="/img/insert.png"/>
<h:outputText value="#{messages['insert']}"/>
</a:commandLink>

This button persists the new contact into the database (by calling the homeSelectedContactHelper.insertNewContact() method) and, using f:setPropertyActionListener, it sets the contactsList property to null, so the list will be read again from the database (reflecting the changes)—after that, it re-renders the list and the detail box to reflect the changes.

Let's see the button code to cancel the insertion:

<a:commandLink ajaxSingle="true" reRender="contactDetail"
rendered="#{!homeSelectedContactHelper.
selectedContactManaged}"
styleClass="image-command-link">

<f:setPropertyActionListener
value="#{false}"
target="#{homeSelectedContactHelper.
selectedContactEditing}"/>

<f:setPropertyActionListener
value="#{null}"
target="#{homeSelectedContactHelper.
selectedContact}"/>

<h:graphicImage value="/img/cancel.png"/>
<h:outputText value="#{messages['cancel']}"/>
</a:commandLink>

This button doesn't call any action method, but it only sets the selectedContact property to null and the selectedContactEditing property to false to "cancel" the insertion action.

We highlighted the ajaxSingle property—this is a very important feature used to avoid the form submission when the button is clicked (so, in this case, when the user clicks on the Cancel button, the form data is not submitted with the Ajax request). We will see it more in depth at the end of the section.

The other button we are going to add is the Save button:

<a:commandLink reRender="contactsList,contactDetail"
action="#{homeSelectedContactHelper.saveContactData}"
rendered="#{homeSelectedContactHelper.selectedContactManaged}"
styleClass="image-command-link">

<f:setPropertyActionListener value="#{false}"
target="#{homeSelectedContactHelper.selectedContactEditing}"/>

<f:setPropertyActionListener value="#{null}"
target="#{homeContactsListHelper.contactsList}"/>

<h:graphicImage value="/img/save.png"/>
<h:outputText value="#{messages['save']}"/>
</a:commandLink>

It simply saves the property modification, sets the contact list property to null, (so, it will be read again from the database) and, sets the edit mode to false (so, the contact detail will be shown).

The Cancel button for an existing contact is almost the same as the one for new contacts:

<a:commandLink ajaxSingle="true" reRender="contactDetail"
rendered="#{homeSelectedContactHelper.selectedContactManaged}"
styleClass="image-command-link">

<f:setPropertyActionListener value="#{false}"
target="#{homeSelectedContactHelper.selectedContactEditing}"/>

<h:graphicImage value="/img/cancel.png"/>
<h:outputText value="#{messages['cancel']}"/>
</a:commandLink>

The only difference is that it doesn't set the selectedContact to null as we would like to see the contact in view mode after canceling the editing.

The last button we are going to insert is the one for deletion:

<a:commandLink ajaxSingle="true" reRender="contactDetail,contactsList"
action="#{homeSelectedContactHelper.deleteSelectedContact}"
rendered="#{homeSelectedContactHelper.selectedContactManaged}"
styleClass="image-command-link">

<f:setPropertyActionListener value="#{null}"
target="#{homeContactsListHelper.contactsList}"/>

<h:graphicImage value="/img/delete.png"/>
<h:outputText value="#{messages['delete']}"/>
</a:commandLink>

It calls the homeSelectedContactHelper.deleteSelectedContact() method that sets to null the selectedContact and the selectedContactEditing (it is a different way to do what we've done for the other action buttons using f:setPropertyListener components). It then sets to null the contactsList property and re-renders the contactList and the contactDetail boxes.

Here is a screenshot of the edit box with the toolbar:

Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 2

JBoss RichFaces 3.3 Enhance your JSF web applications using powerful AJAX components
Published: October 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

>> Continue Reading Build an Advanced Contact Manager using JBoss RichFaces 3.3: Part 3

[ 1 | 2 | 3 ]]

About the Author :


Demetrio Filocamo

Demetrio Filocamo is a computer science engineer with more then 10 years of experience on both Desktop and Web applications development. He works as a freelance in London and collaborates with some companies and universities in Italy. Demetrio has been developing Enterprise Java Applications using open source solutions for the last five years.

Books From Packt

JBoss AS 5 Development
JBoss AS 5 Development

jQuery 1.3 with PHP
jQuery 1.3 with PHP

Joomla! with Flash
Joomla! with Flash

Drools JBoss Rules 5.0 Developer's Guide
Drools JBoss Rules 5.0 Developer's Guide

JBoss Tools 3 Developers Guide
JBoss Tools 3 Developers Guide

Tomcat 6 Developer's Guide
Tomcat 6 Developer's Guide

Apache MyFaces Trinidad 1.2: A Practical Guide
Apache MyFaces Trinidad 1.2: A Practical Guide

jQuery UI 1.6: The User Interface Library for jQuery
jQuery UI 1.6: The User Interface Library for jQuery

 

 

 

Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software