As you probably saw in the previous chapters, PrimeFaces provides a set of amazing components with great design and functionality. AJAX got a special treatment from PrimeFaces and the result is reflected in some great AJAX components. In this recipe, we will present two of them that extend standard JSF components with AJAX, partial processing, and confirmation features. These are: p:commandLink
(extends h:commandLink
) and p:commandButton
(extends h:commandButton
).
We developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library. In addition, we have used PrimeFaces 2.0, which provides support for JSF 2.0. You can download this distribution from http://www.primefaces.org/. The PrimeFaces libraries (including necessary dependencies) are in book code bundle, under the /JSF_libs/PrimeFaces JSF 2.0
folder.
In many sites, when we need to register an ID (a nickname), we have a pre-submit option (usually a link or a button) of type Check ID availability. This facility allows us to check if our ID already exists or is available to be used. This kind of facility fits perfectly to the AJAX aim, since we can refresh only a portion of the page and we don't submit the entire form. Our example will look as the following figure (the arrows identifies the PrimeFaces components that we have used—notice that except the p:commandLink
and p:ajaxStatus
, the rest of them can be replaced by pure JSF components, but with a different visual effect):
Now, let's put together these components to obtain the following page:
… <h:form prependId="false"> <p:panel id="panel" style="width: 420px; margin-bottom:10px;" header="Provide your ID to check ..."> <p:messages showDetail="false" globalOnly="false" /> <h:panelGrid border="0" columns="4"> <h:outputLabel for="nickId" value="ID: *" /> <h:inputText id="nickId" value="#{bean.nick}" required="true" /> <p:commandLink actionListener="#{bean.nickAction}" update="panel" style="margin-right:20px;"> <h:outputText value="Check ID availability" /> </p:commandLink> <p:ajaxStatus style="height:16px"> <f:facet name="start"> <h:graphicImage value="resources/images/ajaxloading.gif" /> </f:facet> <f:facet name="complete"> <h:outputText value="" /> </f:facet> </p:ajaxStatus> </h:panelGrid> </p:panel> </h:form> …
Now, let's identify the main parts of this page. The first thing we did in the page was to set the form
tag's prependId
attribute to false
so that we can refer to component IDs without prepending the form's ID. In Ajax applications, you often have to refer to client IDs. Without the prependId
attribute, you'd have to add the form ID to every client ID reference, which adds extra bytes to network transactions and is a pain to type.
Next, we have used a PrimeFaces panel (p:panel), which will contain our design stuff (you can think of it as a normal HTML <div>
). This panel will be refreshed after the AJAX transaction completes, and for this, it is very important to specify the panel id
attribute.
Going further, we have a another PrimeFaces component, tagged p:messages
. These components are highly customizable and pre-skinned versions of standard message components. We use it for displaying one of the messages This ID is available! or This ID is not available!
Next, we have a simple panel grid and an h:inputText
. In this component, the user specifies the desired ID, which is mapped by the nick String
property in a managed bean. The ID is required.
Now, comes the main part of our recipe. We use the p:commandLink
component to take advantage of the AJAX support. Since this is very similar to the JSF core component, h:commandLink
, it is very easy to use and understand—notice that we don't have any special code that reveal that AJAX is used. Notice that we have set the update
attribute with the value of the panel id
; therefore, the panel will be updated after the AJAX transaction completes. The actionListener
attribute indicates that the nickAction
method should deal with this transaction—this method must get an ActionEvent
instance, and it is listed next:
public void nickAction(ActionEvent actionEvent) { Random check = new Random(); int val = check.nextInt(100); if (val < 50) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "This ID is available!", "")); } else { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "This ID is not available!", "")); } }
Of course, in the real world, you will replace our random stuff with a check against a database, web service, and so on.
The last part of our form uses the p:ajaxStatus
Primefaces component. This component can monitor the AJAX transaction's status (such as transaction started or transaction completed) and we have used it to display a picture that signals to the user that something is going on, and he or she should wait for the process to end. Without this "visual flag", the user has no idea that something is happening behind the scenes.
The process is simple and starts with the user providing an ID. The ID is checked (usually against a database) when the user press the link rendered by the p:commandLink
component. When this action is fired up, the nickAction
method is called and the AJAX request status is monitored by the p:ajaxStatus
and rendered accordingly by displaying or hiding a picture. The AJAX result in our example is reflected in two info messages, but you can do anything else.
Similar to p:commandLink
, we have p:commandButton
. The main difference between these two consists in the fact that h:commandButton
supports an attribute named async
(in older versions it is known as ajax
) that takes a Boolean value. If it is set to true
(default) then the submission would be made with Ajax. As per the example, if we want to use a button instead of the previous link, we can replace it as shown next:
… <p:commandButton async="true" value="Check ID availability" update="panel" actionListener="#{bean.nickAction}" style="margin-right:20px;"/> …
The code bundled with this book contains a complete example of this recipe. The project can be opened with NetBeans 6.8 and it is named: PrimeFaces_CommandLink_and_CommandButton.
You also may want to check:
PrimeFaces tag documentation: http://primefaces.prime.com.tr/docs/tag/.
PrimeFaces home page: http://www.primefaces.org/.
PrimeFaces ShowCase: http://www.primefaces.org:8080/prime-showcase/ui/imageCropperExternal.jsf.