ajax4jsf—more than 100 AJAX components

"RichFaces is a component library for JSF and an advanced framework for easily integrating AJAX capabilities into business applications". More than 100 AJAX components can be found under the RichFaces libraries, a4j (ajax4jsf) and rich. Some of the most impressive components are listed next:

  • a4j:support (this is available starting with RichFaces 3.0.0 and "it is the most important core component in the RichFaces library. It enriches any existing non-Ajax JSF or RichFaces component with Ajax capability. All other RichFaces Ajax components are based on the same principles <a4j:support> has"). Notice that starting with RichFaces 4.0, is possible that this tag will be replaced with one named a4j:ajax.
  • a4j:commandLink
  • a4j:commandButton
  • a4j:push
  • a4j:mediaOutput
  • a4j:status
  • a4j:jsFunction
  • a4j:log
  • a4j:outputPanel

In this recipe, we will develop two examples with a4j:support and one example for a4j:commandButton and a4j:commandLink.

Getting ready

We have 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 RichFaces 3.3.3.BETA1 (ajax4jsf included), which provides support for JSF 2.0. You can download this distribution from http://www.jboss.org/richfaces. The RichFaces libraries (including necessary dependencies) are in the book code bundle, under the /JSF_libs/RichFaces JSF 2.0 folder.

How to do it...

The best way to get further is to try to develop an application that exploits ajax4jsf components. Since a4j:support is the most important ajax4jsf component, we try to build an example with it. But, before this, let' see the a4j:support tag's attributes:

Name

Required

Description

action

No

MethodBinding pointing at the application action to be invoked, if this UIComponent is activated by you, during the Apply Request Values or Invoke Application phase of the request processing lifecycle, depending on the value of the immediate property. Type: javax.el.MethodExpression (signature must match java.lang.Object action()).

actionListener

No

MethodBinding pointing at method accepting an ActionEvent with return type void. Type: javax.el.MethodExpression (signature must match void actionListener(javax.faces.event.ActionEvent)).

ajaxSingle

No

Limits JSF tree processing (decoding, conversion, validation, and model updating) only to a component that sends the request. Type: javax.el.ValueExpression (must evaluate to boolean).

value

No

The initial value of this component.

binding

No

The attribute takes a value-binding expression for a component property of a backing bean. Type: javax.el.ValueExpression (must evaluate to javax.faces.component.UIComponent).

reRender

No

"Id[s] (in format of call UIComponent.findComponent()) of components, rendered in case of AjaxRequest caused by this component. Can be single id, comma-separated list of IDs, or EL Expression with array or Collection. Type: javax.el.ValueExpression (must evaluate to java.lang.Object)

event

No

Name of JavaScript event property (onclick, onchange, etc.) of parent component, for which we will build AJAX submission code. Type: java.lang.String.

onsubmit

No

The client-side script method to be called before an ajax request is submitted. Type: javax.el.ValueExpression (must evaluate to java.lang.String).

oncomplete

No

The client-side script method to be called after the request is completed. Type: javax.el.ValueExpression (must evaluate to java.lang.String).

The complete documentation of the a4j:support tag can be found at http://docs.jboss.org/richfaces/3.3.1.GA/en/tlddoc/a4j/support.html.

Now, based on these attributes we are ready to develop our first example to test the a4j:support tag. We want to render a text field (h:inputText tag) and, at each key up event, to render the inserted character in capitals using the AJAX mechanism. For this, our main form looks as shown next:

…
<h:form id="myForm">
<h:outputText value="Text:" />
<h:inputText value="#{textBean.text}">
<a4j:support event="onkeyup" reRender="textId"
action="#{textBean.upperText}"/>
</h:inputText>
<h:outputText value="Upper Text:" />
<h:outputText id="textId" value="#{textBean.text}" />
</h:form>
…

The event attribute indicates the event that fires up the AJAX process, the reRender attribute indicates the id of the component to be re-rendered when AJAX completes, and the action attribute indicates a method that is executed to convert characters from lowercase to uppercase—the AJAX business logic. The method is listed in the following bean:

@ManagedBean(name="textBean")
@RequestScoped
public class TextBean {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public void upperText() {
this.text = this.text.toUpperCase();
}
}

Now, let's develop a more complex example, and we will try to render three radio buttons (h:selectOneRadio tag) and, when the current radio button is changed, to render a table (h:dataTable tag) with a different content. The radio buttons will represent three automobile manufacturers' names and the table will represent the list of cars from the selected company. Obviously, we want to change the table's content through AJAX mechanism. The view is listed next:

…
<h:form id="myForm">
<h:selectOneRadio id="companyId" value="#{carsBean.carCompany}"
valueChangeListener="#{carsBean.companyChanged}">
<f:selectItems value="#{carsBean.allCars}"/>
<a4j:support event="onchange" reRender="carsId" />
</h:selectOneRadio>
<h:outputText value="Available cars for company
#{carsBean.carCompany}:" />
<h:dataTable id="carsId" value="#{carsBean.companyCars}" var="car">
<h:column>
<h:outputText value="#{car}" />
</h:column>
</h:dataTable>
</h:form>
…

This time the event attribute indicates the onchange event and the re-rendered component is a table. The bean behind the scenes is:

package bean;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
@ManagedBean(name = "carsBean")
@RequestScoped
public class CarsBean {
private String carCompany = "Renault";
private String carName;
public List<SelectItem> allCars = new ArrayList<SelectItem>();
public List<String> companyCars = new ArrayList<String>();
private static final String[] carsRenault = new
String[]{"Clio", "Clio Estate", "Clio RS", "Symbol",
"Fluence", "Sedan", "Megane", "Megane Coupe",
"Megan Sport Tourer", "Scenic", "Grand Scenic", "Kangoo",
"Coupe", "Koleos", "Espace", "Laguna", "Laguna Estate"};
private static final String[] carsFiat = new
String[]{"500", "Panda", "Punto Classic", "Grande Punto
Unico", "Albea", "Bravo", "Linea", "Croma",
"Sedici", "Doblo Panorama"};
private static final String[] carsDacia = new
String[]{"Sandero", "Logan", "Logan MCV", "Van", "Pick-up"};
public CarsBean() {
allCars.add(new SelectItem("Renault", "Renault"));
allCars.add(new SelectItem("Fiat", "Fiat"));
allCars.add(new SelectItem("Dacia", "Dacia"));
for (int i = 0; i < carsRenault.length; i++) {
companyCars.add(carsRenault[i]);
}
}
public void companyChanged(ValueChangeEvent event) {
companyCars.clear();
if (((String) event.getNewValue()).equals("Renault")) {
addCompanyCars(carsRenault);
}
if (((String) event.getNewValue()).equals("Fiat")) {
addCompanyCars(carsFiat);
}
if (((String) event.getNewValue()).equals("Dacia")) {
addCompanyCars(carsDacia);
}
}
private void addCompanyCars(String[] currentCars) {
companyCars.clear();
for (int i = 0; i < currentCars.length; i++) {
companyCars.add(currentCars[i]);
}
}
public String getCarCompany() {
return carCompany;
}
public void setCarCompany(String carCompany) {
this.carCompany = carCompany;
}
public String getCarName() {
return carName;
}
public void setCarName(String carName) {
this.carName = carName;
}
public List<SelectItem> getAllCars() {
return allCars;
}
public void setAllCars(List<SelectItem> allCars) {
this.allCars = allCars;
}
public List<String> getCompanyCars() {
return companyCars;
}
public void setCompanyCars(List<String> companyCars) {
this.companyCars = companyCars;
}
}

The most important method here is companyChanged, which populates a list with the cars' names depending on the selected company. This method is called through the valueChangeListener attribute of the h:selectOneRadio tag, not through the action attribute of a4j:support tag.

How it works...

The mechanism of a4j:support is pretty straightforward. The event attribute will indicate the mouse/keyboard event that must happen to start the AJAX process. Now, the client AJAX business logic is executed and the desired modifications take place—the method responsible with client AJAX business logic is called through a4j:support attributes, action, and/or actionListener or similar attributes of tags that wrap the a4j:support tag. This is the basic mechanism, but we have to be aware of the entire suite of attributes that allows us to have full control over this AJAX process. The most important thing, as you can see, is that the a4j:support component in not tied to any other component, which means that we can use it to implement AJAX support to any JSF component that can be logically involded with AJAX.

If you take a look in the web.xml descriptor, you will notice that ajax4jsf is implemented as a filter. This is an important aspect, because when a user makes an ajax4jsf request, a JavaScript event is fired and it is processed by the AJAX Engine, commonly on the client side. Next, the original request is submitted by the AJAX Engine to ajax4jsf filter. At this step, a set of XML filters will convert the data into XML format and the request reaches the original Faces Servlet. Keep in mind that it is very possible that this configuration will not be necessary in RichFaces 4.0.

There's more...

Next you will see how to use another two ajax4jsf components, as follows:

a4j:commandLink:"The <a4j:commandLink> component is very similar to the <h:commandLink> component, the only difference is that an Ajax form submit is generated on a click and it allows dynamic re-rendering after a response comes back. It's not necessary to plug any support into the component, as Ajax support is already built in."—see home page at: http://docs.jboss.org/richfaces/3.3.1.GA/en/devguide/html/a4j_commandLink.html.

a4j:commandButton:"The <a4j:commandButton> component is very similar to JSF <h:commandButton>, the only difference is that an Ajax form submit is generated on a click and it allows dynamic re-rendering after a response comes back."—see home page at http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/a4j_commandButton.html.

Now, we can use these two ajax4jsf components to develop the following JSF page:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@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"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Demo of a4j:commandLink and a4j:commandButton</title>
</head>
<body>
<f:view>
<h:outputText value="Set page number manually:"/>
<h:panelGrid id="panel1ID" columns="2"
border="0" style="width:600px;">
<h:outputText value="a4j:commandLink Example" />
<a4j:form>
<h:outputText value="Set page number: " />
<h:inputText value="#{book.pagenr}" />
<a4j:commandLink value="Get Page Number" reRender="pagesID" />
<h:panelGroup id="pagesID">
<h:outputText value="Pages: "
rendered="#{not empty book.pagenr}" />
<h:outputText value="#{book.pagenr}" />
<h:outputText value="!" rendered="#{not empty book.pagenr}" />
</h:panelGroup>
</a4j:form>
</h:panelGrid>
<br />
<h:outputText value="Increase/decrease page number using buttons
(the start page is the one setted manually):"/>
<h:panelGrid id="panel2ID" columns="3"
border="0" style="width:600px;">
<h:outputText value="a4j:commandButton Example" />
<a4j:form>
<a4j:commandButton action="#{book.pageItForward}"
value="Page It Forward" reRender="pifID" />
<a4j:commandButton action="#{book.pageItBackwards}"
value="Page It Backwards" reRender="pifID" />
</a4j:form>
<h:outputText value="Page number:#{book.pagenr}" id="pifID" />
</h:panelGrid>
</f:view>
</body>
</html>

The Book bean looks like this:

package a4jdemo;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
@ManagedBean(name = "book")
@SessionScoped
public class Book {
private int pagenr = 1;
public int getPagenr() {
return pagenr;
}
public void setPagenr(int pagenr) {
this.pagenr = pagenr;
}
public void pageItForward() {
pagenr = pagenr + 1;
}
public void pageItBackwards() {
pagenr = pagenr - 1;
}
}

The application output can be seen in the following screenshot:

There's more...

Other ajax4jsf component

Some other ajax4jsf components are:

  • <a4j:ajaxListener>
  • <a4j:keepAlive>
  • <a4j:actionparam>
  • <a4j:form>
  • <a4j:htmlCommandLink>
  • <a4j:jsFunction>
  • <a4j:include>
  • <a4j:loadBundle>
  • <a4j:loadScript>
  • <a4j:loadStyle>
  • <a4j:log>
  • <a4j:mediaOutput>
  • <a4j:outputPanel>
  • <a4j:page>
  • <a4j:poll>
  • <a4j:portlet>
  • <a4j:push>
  • <a4j:region>
  • <a4j:repeat>
  • <a4j:status>
  • <a4j:support>

See also

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:

  • Using_ajax4jsf_support_component_I
  • Using_ajax4jsf_support_component_II
  • Using_ajax4jsf_commandLink_and_commandButton

An ajax4jsf developer guide can be found at http://labs.jboss.com/file-access/default/members/jbossajax4jsf/freezone/docs/devguide/en/html/index.html.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset