9 min read

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="main/contactView.xhtml"/>
</a:outputPanel>
<a:outputPanel
rendered="#{homeSelectedContactHelper.
selectedContact!=null and
homeSelectedContactHelper.
selectedContactEditing==true}">
<ui:include src="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

LEAVE A REPLY

Please enter your comment!
Please enter your name here